diff options
Diffstat (limited to 'lib/Target/Mips')
50 files changed, 2300 insertions, 873 deletions
diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index d054578deb67..d407774574be 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -7,47 +7,67 @@ // //===----------------------------------------------------------------------===// +#include "MCTargetDesc/MipsABIFlagsSection.h" #include "MCTargetDesc/MipsABIInfo.h" #include "MCTargetDesc/MipsMCExpr.h" #include "MCTargetDesc/MipsMCTargetDesc.h" -#include "MipsRegisterInfo.h" -#include "MipsTargetObjectFile.h" #include "MipsTargetStreamer.h" #include "MCTargetDesc/MipsBaseInfo.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" +#include "llvm/ADT/Twine.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" -#include "llvm/MC/MCInstBuilder.h" +#include "llvm/MC/MCInstrDesc.h" +#include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/MC/MCParser/MCAsmParserExtension.h" #include "llvm/MC/MCParser/MCParsedAsmOperand.h" #include "llvm/MC/MCParser/MCTargetAsmParser.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCSymbolELF.h" +#include "llvm/MC/MCValue.h" +#include "llvm/MC/SubtargetFeature.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ELF.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/SMLoc.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <cstdint> #include <memory> +#include <string> +#include <utility> using namespace llvm; #define DEBUG_TYPE "mips-asm-parser" namespace llvm { + class MCInstrInfo; -} + +} // end namespace llvm namespace { + class MipsAssemblerOptions { public: - MipsAssemblerOptions(const FeatureBitset &Features_) : - ATReg(1), Reorder(true), Macro(true), Features(Features_) {} + MipsAssemblerOptions(const FeatureBitset &Features_) : Features(Features_) {} MipsAssemblerOptions(const MipsAssemblerOptions *Opts) { ATReg = Opts->getATRegIndex(); @@ -84,12 +104,13 @@ public: static const FeatureBitset AllArchRelatedMask; private: - unsigned ATReg; - bool Reorder; - bool Macro; + unsigned ATReg = 1; + bool Reorder = true; + bool Macro = true; FeatureBitset Features; }; -} + +} // end anonymous namespace const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = { Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3, @@ -103,6 +124,7 @@ const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = { }; namespace { + class MipsAsmParser : public MCTargetAsmParser { MipsTargetStreamer &getTargetStreamer() { MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer(); @@ -147,6 +169,8 @@ class MipsAsmParser : public MCTargetAsmParser { bool parseBracketSuffix(StringRef Name, OperandVector &Operands); + bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID); + bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) override; @@ -252,6 +276,18 @@ class MipsAsmParser : public MCTargetAsmParser { bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI); + bool expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); + + bool expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); + + bool expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); + + bool expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); + bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI, bool IsLoad); @@ -339,6 +375,8 @@ class MipsAsmParser : public MCTargetAsmParser { /// This should be used in pseudo-instruction expansions which need AT. unsigned getATReg(SMLoc Loc); + bool canUseATReg(); + bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI); @@ -466,9 +504,11 @@ public: bool isGP64bit() const { return getSTI().getFeatureBits()[Mips::FeatureGP64Bit]; } + bool isFP64bit() const { return getSTI().getFeatureBits()[Mips::FeatureFP64Bit]; } + const MipsABIInfo &getABI() const { return ABI; } bool isABI_N32() const { return ABI.IsN32(); } bool isABI_N64() const { return ABI.IsN64(); } @@ -484,48 +524,63 @@ public: bool inMicroMipsMode() const { return getSTI().getFeatureBits()[Mips::FeatureMicroMips]; } + bool hasMips1() const { return getSTI().getFeatureBits()[Mips::FeatureMips1]; } + bool hasMips2() const { return getSTI().getFeatureBits()[Mips::FeatureMips2]; } + bool hasMips3() const { return getSTI().getFeatureBits()[Mips::FeatureMips3]; } + bool hasMips4() const { return getSTI().getFeatureBits()[Mips::FeatureMips4]; } + bool hasMips5() const { return getSTI().getFeatureBits()[Mips::FeatureMips5]; } + bool hasMips32() const { return getSTI().getFeatureBits()[Mips::FeatureMips32]; } + bool hasMips64() const { return getSTI().getFeatureBits()[Mips::FeatureMips64]; } + bool hasMips32r2() const { return getSTI().getFeatureBits()[Mips::FeatureMips32r2]; } + bool hasMips64r2() const { return getSTI().getFeatureBits()[Mips::FeatureMips64r2]; } + bool hasMips32r3() const { return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]); } + bool hasMips64r3() const { return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]); } + bool hasMips32r5() const { return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]); } + bool hasMips64r5() const { return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]); } + bool hasMips32r6() const { return getSTI().getFeatureBits()[Mips::FeatureMips32r6]; } + bool hasMips64r6() const { return getSTI().getFeatureBits()[Mips::FeatureMips64r6]; } @@ -533,15 +588,19 @@ public: bool hasDSP() const { return getSTI().getFeatureBits()[Mips::FeatureDSP]; } + bool hasDSPR2() const { return getSTI().getFeatureBits()[Mips::FeatureDSPR2]; } + bool hasDSPR3() const { return getSTI().getFeatureBits()[Mips::FeatureDSPR3]; } + bool hasMSA() const { return getSTI().getFeatureBits()[Mips::FeatureMSA]; } + bool hasCnMips() const { return (getSTI().getFeatureBits()[Mips::FeatureCnMips]); } @@ -627,9 +686,6 @@ public: } } }; -} - -namespace { /// MipsOperand - Instances of this class represent a parsed Mips machine /// instruction. @@ -671,6 +727,22 @@ public: MipsOperand(KindTy K, MipsAsmParser &Parser) : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {} + ~MipsOperand() override { + switch (Kind) { + case k_Immediate: + break; + case k_Memory: + delete Mem.Base; + break; + case k_RegList: + delete RegList.List; + case k_RegisterIndex: + case k_Token: + case k_RegPair: + break; + } + } + private: /// For diagnostics, and checking the assembler temporary MipsAsmParser &AsmParser; @@ -716,7 +788,7 @@ private: const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E, MipsAsmParser &Parser) { - auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser); + auto Op = llvm::make_unique<MipsOperand>(k_RegisterIndex, Parser); Op->RegIdx.Index = Index; Op->RegIdx.RegInfo = RegInfo; Op->RegIdx.Kind = RegKind; @@ -896,6 +968,16 @@ public: /// Render the operand to an MCInst as a GPR32 /// Asserts if the wrong number of operands are requested, or the operand /// is not a k_RegisterIndex compatible with RegKind_GPR + void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::createReg(getGPR32Reg())); + } + + void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::createReg(getGPR32Reg())); + } + void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::createReg(getGPR32Reg())); @@ -1104,45 +1186,58 @@ public: // $0/$zero here so that MCK_ZERO works correctly. return isGPRAsmReg() && RegIdx.Index == 0; } + bool isRegIdx() const { return Kind == k_RegisterIndex; } bool isImm() const override { return Kind == k_Immediate; } + bool isConstantImm() const { int64_t Res; return isImm() && getImm()->evaluateAsAbsolute(Res); } + bool isConstantImmz() const { return isConstantImm() && getConstantImm() == 0; } + template <unsigned Bits, int Offset = 0> bool isConstantUImm() const { return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset); } + template <unsigned Bits> bool isSImm() const { return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm(); } + template <unsigned Bits> bool isUImm() const { return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm(); } + template <unsigned Bits> bool isAnyImm() const { return isConstantImm() ? (isInt<Bits>(getConstantImm()) || isUInt<Bits>(getConstantImm())) : isImm(); } + template <unsigned Bits, int Offset = 0> bool isConstantSImm() const { return isConstantImm() && isInt<Bits>(getConstantImm() - Offset); } + template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const { return isConstantImm() && getConstantImm() >= Bottom && getConstantImm() <= Top; } + bool isToken() const override { // Note: It's not possible to pretend that other operand kinds are tokens. // The matcher emitter checks tokens first. return Kind == k_Token; } + bool isMem() const override { return Kind == k_Memory; } + bool isConstantMemOff() const { return isMem() && isa<MCConstantExpr>(getMemOff()); } + // Allow relocation operators. // FIXME: This predicate and others need to look through binary expressions // and determine whether a Value is a constant or not. @@ -1160,28 +1255,34 @@ public: bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr); return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant()); } + bool isMemWithGRPMM16Base() const { return isMem() && getMemBase()->isMM16AsmReg(); } + template <unsigned Bits> bool isMemWithUimmOffsetSP() const { return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff()) && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP); } + template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const { return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff()) && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP); } + template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const { return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::GP); } + template <unsigned Bits, unsigned ShiftLeftAmount> bool isScaledUImm() const { return isConstantImm() && isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm()); } + template <unsigned Bits, unsigned ShiftLeftAmount> bool isScaledSImm() const { if (isConstantImm() && isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm())) @@ -1193,6 +1294,7 @@ public: bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr); return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant()); } + bool isRegList16() const { if (!isRegList()) return false; @@ -1217,14 +1319,18 @@ public: return true; } + bool isInvNum() const { return Kind == k_Immediate; } + bool isLSAImm() const { if (!isConstantImm()) return false; int64_t Val = getConstantImm(); return 1 <= Val && Val <= 4; } + bool isRegList() const { return Kind == k_RegList; } + bool isMovePRegPair() const { if (Kind != k_RegList || RegList.List->size() != 2) return false; @@ -1257,6 +1363,7 @@ public: assert(Kind == k_Token && "Invalid access!"); return StringRef(Tok.Data, Tok.Length); } + bool isRegPair() const { return Kind == k_RegPair && RegIdx.Index <= 30; } @@ -1310,7 +1417,7 @@ public: static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S, MipsAsmParser &Parser) { - auto Op = make_unique<MipsOperand>(k_Token, Parser); + auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser); Op->Tok.Data = Str.data(); Op->Tok.Length = Str.size(); Op->StartLoc = S; @@ -1385,7 +1492,7 @@ public: static std::unique_ptr<MipsOperand> CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) { - auto Op = make_unique<MipsOperand>(k_Immediate, Parser); + auto Op = llvm::make_unique<MipsOperand>(k_Immediate, Parser); Op->Imm.Val = Val; Op->StartLoc = S; Op->EndLoc = E; @@ -1395,7 +1502,7 @@ public: static std::unique_ptr<MipsOperand> CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S, SMLoc E, MipsAsmParser &Parser) { - auto Op = make_unique<MipsOperand>(k_Memory, Parser); + auto Op = llvm::make_unique<MipsOperand>(k_Memory, Parser); Op->Mem.Base = Base.release(); Op->Mem.Off = Off; Op->StartLoc = S; @@ -1406,9 +1513,9 @@ public: static std::unique_ptr<MipsOperand> CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc, MipsAsmParser &Parser) { - assert (Regs.size() > 0 && "Empty list not allowed"); + assert(Regs.size() > 0 && "Empty list not allowed"); - auto Op = make_unique<MipsOperand>(k_RegList, Parser); + auto Op = llvm::make_unique<MipsOperand>(k_RegList, Parser); Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end()); Op->StartLoc = StartLoc; Op->EndLoc = EndLoc; @@ -1418,7 +1525,7 @@ public: static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP, SMLoc S, SMLoc E, MipsAsmParser &Parser) { - auto Op = make_unique<MipsOperand>(k_RegPair, Parser); + auto Op = llvm::make_unique<MipsOperand>(k_RegPair, Parser); Op->RegIdx.Index = MOP.RegIdx.Index; Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo; Op->RegIdx.Kind = MOP.RegIdx.Kind; @@ -1427,14 +1534,25 @@ public: return Op; } + bool isGPRZeroAsmReg() const { + return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0; + } + + bool isGPRNonZeroAsmReg() const { + return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 && + RegIdx.Index <= 31; + } + bool isGPRAsmReg() const { return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31; } + bool isMM16AsmReg() const { if (!(isRegIdx() && RegIdx.Kind)) return false; return ((RegIdx.Index >= 2 && RegIdx.Index <= 7) || RegIdx.Index == 16 || RegIdx.Index == 17); + } bool isMM16AsmRegZero() const { if (!(isRegIdx() && RegIdx.Kind)) @@ -1443,42 +1561,53 @@ public: (RegIdx.Index >= 2 && RegIdx.Index <= 7) || RegIdx.Index == 17); } + bool isMM16AsmRegMoveP() const { if (!(isRegIdx() && RegIdx.Kind)) return false; return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) || (RegIdx.Index >= 16 && RegIdx.Index <= 20)); } + bool isFGRAsmReg() const { // AFGR64 is $0-$15 but we handle this in getAFGR64() return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31; } + bool isHWRegsAsmReg() const { return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31; } + bool isCCRAsmReg() const { return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31; } + bool isFCCAsmReg() const { if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC)) return false; return RegIdx.Index <= 7; } + bool isACCAsmReg() const { return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3; } + bool isCOP0AsmReg() const { return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31; } + bool isCOP2AsmReg() const { return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31; } + bool isCOP3AsmReg() const { return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31; } + bool isMSA128AsmReg() const { return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31; } + bool isMSACtrlAsmReg() const { return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7; } @@ -1488,22 +1617,6 @@ public: /// getEndLoc - Get the location of the last token of this operand. SMLoc getEndLoc() const override { return EndLoc; } - virtual ~MipsOperand() { - switch (Kind) { - case k_Immediate: - break; - case k_Memory: - delete Mem.Base; - break; - case k_RegList: - delete RegList.List; - case k_RegisterIndex: - case k_Token: - case k_RegPair: - break; - } - } - void print(raw_ostream &OS) const override { switch (Kind) { case k_Immediate: @@ -1553,11 +1666,15 @@ public: } } }; // class MipsOperand -} // namespace + +} // end anonymous namespace namespace llvm { + extern const MCInstrDesc MipsInsts[]; -} + +} // end namespace llvm + static const MCInstrDesc &getInstDesc(unsigned Opcode) { return MipsInsts[Opcode]; } @@ -1785,6 +1902,61 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, } } + // Warn on division by zero. We're checking here as all instructions get + // processed here, not just the macros that need expansion. + // + // The MIPS backend models most of the divison instructions and macros as + // three operand instructions. The pre-R6 divide instructions however have + // two operands and explicitly define HI/LO as part of the instruction, + // not in the operands. + unsigned FirstOp = 1; + unsigned SecondOp = 2; + switch (Inst.getOpcode()) { + default: + break; + case Mips::SDivIMacro: + case Mips::UDivIMacro: + case Mips::DSDivIMacro: + case Mips::DUDivIMacro: + if (Inst.getOperand(2).getImm() == 0) { + if (Inst.getOperand(1).getReg() == Mips::ZERO || + Inst.getOperand(1).getReg() == Mips::ZERO_64) + Warning(IDLoc, "dividing zero by zero"); + else + Warning(IDLoc, "division by zero"); + } + break; + case Mips::DSDIV: + case Mips::SDIV: + case Mips::UDIV: + case Mips::DUDIV: + case Mips::UDIV_MM: + case Mips::SDIV_MM: + FirstOp = 0; + SecondOp = 1; + case Mips::SDivMacro: + case Mips::DSDivMacro: + case Mips::UDivMacro: + case Mips::DUDivMacro: + case Mips::DIV: + case Mips::DIVU: + case Mips::DDIV: + case Mips::DDIVU: + case Mips::DIVU_MMR6: + case Mips::DDIVU_MM64R6: + case Mips::DIV_MMR6: + case Mips::DDIV_MM64R6: + if (Inst.getOperand(SecondOp).getReg() == Mips::ZERO || + Inst.getOperand(SecondOp).getReg() == Mips::ZERO_64) { + if (Inst.getOperand(FirstOp).getReg() == Mips::ZERO || + Inst.getOperand(FirstOp).getReg() == Mips::ZERO_64) + Warning(IDLoc, "dividing zero by zero"); + else + Warning(IDLoc, "division by zero"); + } + break; + } + // For PIC code convert unconditional jump to unconditional branch. if ((Inst.getOpcode() == Mips::J || Inst.getOpcode() == Mips::J_MM) && inPicMode()) { @@ -2135,6 +2307,8 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; case Mips::BneImm: case Mips::BeqImm: + case Mips::BEQLImmMacro: + case Mips::BNELImmMacro: return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; case Mips::BLT: case Mips::BLE: @@ -2170,15 +2344,19 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, case Mips::BGTULImmMacro: return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; case Mips::SDivMacro: + case Mips::SDivIMacro: return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail : MER_Success; case Mips::DSDivMacro: + case Mips::DSDivIMacro: return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail : MER_Success; case Mips::UDivMacro: + case Mips::UDivIMacro: return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail : MER_Success; case Mips::DUDivMacro: + case Mips::DUDivIMacro: return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail : MER_Success; case Mips::PseudoTRUNC_W_S: @@ -2200,11 +2378,24 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, case Mips::Usw: return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; case Mips::NORImm: + case Mips::NORImm64: + return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; + case Mips::SLTImm64: + if (isInt<16>(Inst.getOperand(2).getImm())) { + Inst.setOpcode(Mips::SLTi64); + return MER_NotAMacro; + } + return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; + case Mips::SLTUImm64: + if (isInt<16>(Inst.getOperand(2).getImm())) { + Inst.setOpcode(Mips::SLTiu64); + return MER_NotAMacro; + } return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; - case Mips::ADDi: - case Mips::ADDiu: - case Mips::SLTi: - case Mips::SLTiu: + case Mips::ADDi: case Mips::ADDi_MM: + case Mips::ADDiu: case Mips::ADDiu_MM: + case Mips::SLTi: case Mips::SLTi_MM: + case Mips::SLTiu: case Mips::SLTiu_MM: if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) { int64_t ImmValue = Inst.getOperand(2).getImm(); @@ -2214,9 +2405,9 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, : MER_Success; } return MER_NotAMacro; - case Mips::ANDi: - case Mips::ORi: - case Mips::XORi: + case Mips::ANDi: case Mips::ANDi_MM: case Mips::ANDi64: + case Mips::ORi: case Mips::ORi_MM: case Mips::ORi64: + case Mips::XORi: case Mips::XORi_MM: case Mips::XORi64: if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) { int64_t ImmValue = Inst.getOperand(2).getImm(); @@ -2240,6 +2431,17 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; case Mips::ABSMacro: return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; + case Mips::MULImmMacro: + case Mips::DMULImmMacro: + return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; + case Mips::MULOMacro: + case Mips::DMULOMacro: + return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; + case Mips::MULOUMacro: + case Mips::DMULOUMacro: + return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; + case Mips::DMULMacro: + return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; case Mips::LDMacro: case Mips::SDMacro: return expandLoadStoreDMacro(Inst, IDLoc, Out, STI, @@ -2392,7 +2594,6 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg, uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff; uint16_t Bits15To0 = ImmValue & 0xffff; - if (!Is32BitImm && !isInt<32>(ImmValue)) { // Traditional behaviour seems to special case this particular value. It's // not clear why other masks are handled differently. @@ -2618,20 +2819,24 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr, // This is the 64-bit symbol address expansion. if (ABI.ArePtrs64bit() && isGP64bit()) { - // We always need AT for the 64-bit expansion. - // If it is not available we exit. - unsigned ATReg = getATReg(IDLoc); - if (!ATReg) - return true; + // We need AT for the 64-bit expansion in the cases where the optional + // source register is the destination register and for the superscalar + // scheduled form. + // + // If it is not available we exit if the destination is the same as the + // source register. const MipsMCExpr *HighestExpr = MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext()); const MipsMCExpr *HigherExpr = MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext()); - if (UseSrcReg && - getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, - SrcReg)) { + bool RdRegIsRsReg = + getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg); + + if (canUseATReg() && UseSrcReg && RdRegIsRsReg) { + unsigned ATReg = getATReg(IDLoc); + // If $rs is the same as $rd: // (d)la $rd, sym($rd) => lui $at, %highest(sym) // daddiu $at, $at, %higher(sym) @@ -2653,29 +2858,65 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr, TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI); return false; - } + } else if (canUseATReg() && !RdRegIsRsReg) { + unsigned ATReg = getATReg(IDLoc); - // Otherwise, if the $rs is different from $rd or if $rs isn't specified: - // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym) - // lui $at, %hi(sym) - // daddiu $rd, $rd, %higher(sym) - // daddiu $at, $at, %lo(sym) - // dsll32 $rd, $rd, 0 - // daddu $rd, $rd, $at - // (daddu $rd, $rd, $rs) - TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc, - STI); - TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI); - TOut.emitRRX(Mips::DADDiu, DstReg, DstReg, - MCOperand::createExpr(HigherExpr), IDLoc, STI); - TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), - IDLoc, STI); - TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI); - TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI); - if (UseSrcReg) - TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI); + // If the $rs is different from $rd or if $rs isn't specified and we + // have $at available: + // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym) + // lui $at, %hi(sym) + // daddiu $rd, $rd, %higher(sym) + // daddiu $at, $at, %lo(sym) + // dsll32 $rd, $rd, 0 + // daddu $rd, $rd, $at + // (daddu $rd, $rd, $rs) + // + // Which is preferred for superscalar issue. + TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc, + STI); + TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI); + TOut.emitRRX(Mips::DADDiu, DstReg, DstReg, + MCOperand::createExpr(HigherExpr), IDLoc, STI); + TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), + IDLoc, STI); + TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI); + TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI); + if (UseSrcReg) + TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI); - return false; + return false; + } else if (!canUseATReg() && !RdRegIsRsReg) { + // Otherwise, synthesize the address in the destination register + // serially: + // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym) + // daddiu $rd, $rd, %higher(sym) + // dsll $rd, $rd, 16 + // daddiu $rd, $rd, %hi(sym) + // dsll $rd, $rd, 16 + // daddiu $rd, $rd, %lo(sym) + TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc, + STI); + TOut.emitRRX(Mips::DADDiu, DstReg, DstReg, + MCOperand::createExpr(HigherExpr), IDLoc, STI); + TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI); + TOut.emitRRX(Mips::DADDiu, DstReg, DstReg, + MCOperand::createExpr(HiExpr), IDLoc, STI); + TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI); + TOut.emitRRX(Mips::DADDiu, DstReg, DstReg, + MCOperand::createExpr(LoExpr), IDLoc, STI); + if (UseSrcReg) + TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI); + + return false; + } else { + // We have a case where SrcReg == DstReg and we don't have $at + // available. We can't expand this case, so error out appropriately. + assert(SrcReg == DstReg && !canUseATReg() && + "Could have expanded dla but didn't?"); + reportParseError(IDLoc, + "pseudo-instruction requires $at, which is not available"); + return true; + } } // And now, the 32-bit symbol address expansion: @@ -2769,6 +3010,8 @@ bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) && "expected immediate or expression operand"); + bool IsLikely = false; + unsigned OpCode = 0; switch(Inst.getOpcode()) { case Mips::BneImm: @@ -2777,16 +3020,29 @@ bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, case Mips::BeqImm: OpCode = Mips::BEQ; break; + case Mips::BEQLImmMacro: + OpCode = Mips::BEQL; + IsLikely = true; + break; + case Mips::BNELImmMacro: + OpCode = Mips::BNEL; + IsLikely = true; + break; default: llvm_unreachable("Unknown immediate branch pseudo-instruction."); break; } int64_t ImmValue = ImmOp.getImm(); - if (ImmValue == 0) - TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc, - STI); - else { + if (ImmValue == 0) { + if (IsLikely) { + TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, + MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI); + TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI); + } else + TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc, + STI); + } else { warnIfNoMacro(IDLoc); unsigned ATReg = getATReg(IDLoc); @@ -2797,7 +3053,12 @@ bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, IDLoc, Out, STI)) return true; - TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI); + if (IsLikely) { + TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, + MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI); + TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI); + } else + TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI); } return false; } @@ -2904,9 +3165,9 @@ bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, unsigned Opcode = Inst.getOpcode(); unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM; - assert (Inst.getOperand(OpNum - 1).isImm() && - Inst.getOperand(OpNum - 2).isReg() && - Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand."); + assert(Inst.getOperand(OpNum - 1).isImm() && + Inst.getOperand(OpNum - 2).isReg() && + Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand."); if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 && Inst.getOperand(OpNum - 1).getImm() >= 0 && @@ -3185,6 +3446,14 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc, return false; } +// Expand a integer division macro. +// +// Notably we don't have to emit a warning when encountering $rt as the $zero +// register, or 0 as an immediate. processInstruction() has already done that. +// +// The destination register can only be $zero when expanding (S)DivIMacro or +// D(S)DivMacro. + bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI, const bool IsMips64, const bool Signed) { @@ -3200,67 +3469,88 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, assert(RsRegOp.isReg() && "expected register operand kind"); unsigned RsReg = RsRegOp.getReg(); - const MCOperand &RtRegOp = Inst.getOperand(2); - assert(RtRegOp.isReg() && "expected register operand kind"); - unsigned RtReg = RtRegOp.getReg(); + unsigned RtReg; + int64_t ImmValue; + + const MCOperand &RtOp = Inst.getOperand(2); + assert((RtOp.isReg() || RtOp.isImm()) && + "expected register or immediate operand kind"); + if (RtOp.isReg()) + RtReg = RtOp.getReg(); + else + ImmValue = RtOp.getImm(); + unsigned DivOp; unsigned ZeroReg; + unsigned SubOp; if (IsMips64) { DivOp = Signed ? Mips::DSDIV : Mips::DUDIV; ZeroReg = Mips::ZERO_64; + SubOp = Mips::DSUB; } else { DivOp = Signed ? Mips::SDIV : Mips::UDIV; ZeroReg = Mips::ZERO; + SubOp = Mips::SUB; } bool UseTraps = useTraps(); - if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) { - if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) - Warning(IDLoc, "dividing zero by zero"); - if (IsMips64) { - if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) { - if (UseTraps) { - TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI); - return false; - } + if (RtOp.isImm()) { + unsigned ATReg = getATReg(IDLoc); + if (!ATReg) + return true; + if (ImmValue == 0) { + if (UseTraps) + TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI); + else TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI); - return false; - } + return false; + } + + if (ImmValue == 1) { + TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI); + return false; + } else if (Signed && ImmValue == -1) { + TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI); + return false; } else { - TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI); + if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue), + false, Inst.getLoc(), Out, STI)) + return true; + TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI); + TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI); return false; } + return true; } + // If the macro expansion of (d)div(u) would always trap or break, insert + // the trap/break and exit. This gives a different result to GAS. GAS has + // an inconsistency/missed optimization in that not all cases are handled + // equivalently. As the observed behaviour is the same, we're ok. if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) { - Warning(IDLoc, "division by zero"); - if (Signed) { - if (UseTraps) { - TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI); - return false; - } - - TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI); + if (UseTraps) { + TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI); return false; } + TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI); + return false; } - // FIXME: The values for these two BranchTarget variables may be different in - // micromips. These magic numbers need to be removed. - unsigned BranchTargetNoTraps; - unsigned BranchTarget; + // Temporary label for first branch traget + MCContext &Context = TOut.getStreamer().getContext(); + MCSymbol *BrTarget; + MCOperand LabelOp; if (UseTraps) { - BranchTarget = IsMips64 ? 12 : 8; TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI); } else { - BranchTarget = IsMips64 ? 20 : 16; - BranchTargetNoTraps = 8; // Branch to the li instruction. - TOut.emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc, STI); + BrTarget = Context.createTempSymbol(); + LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context)); + TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI); } TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI); @@ -3269,6 +3559,9 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI); if (!Signed) { + if (!UseTraps) + TOut.getStreamer().EmitLabel(BrTarget); + TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI); return false; } @@ -3277,15 +3570,23 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, if (!ATReg) return true; + if (!UseTraps) + TOut.getStreamer().EmitLabel(BrTarget); + TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI); + + // Temporary label for the second branch target. + MCSymbol *BrTargetEnd = Context.createTempSymbol(); + MCOperand LabelOpEnd = + MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context)); + + // Branch to the mflo instruction. + TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI); + if (IsMips64) { - // Branch to the mflo instruction. - TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI); TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI); TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI); } else { - // Branch to the mflo instruction. - TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI); TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI); } @@ -3293,10 +3594,12 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI); else { // Branch to the mflo instruction. - TOut.emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, STI); + TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI); TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI); TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI); } + + TOut.getStreamer().EmitLabel(BrTargetEnd); TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI); return false; } @@ -3503,10 +3806,10 @@ bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, const MCSubtargetInfo *STI) { MipsTargetStreamer &TOut = getTargetStreamer(); - assert (Inst.getNumOperands() == 3 && "Invalid operand count"); - assert (Inst.getOperand(0).isReg() && - Inst.getOperand(1).isReg() && - Inst.getOperand(2).isImm() && "Invalid instruction operand."); + assert(Inst.getNumOperands() == 3 && "Invalid operand count"); + assert(Inst.getOperand(0).isReg() && + Inst.getOperand(1).isReg() && + Inst.getOperand(2).isImm() && "Invalid instruction operand."); unsigned ATReg = Mips::NoRegister; unsigned FinalDstReg = Mips::NoRegister; @@ -3514,7 +3817,7 @@ bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, unsigned SrcReg = Inst.getOperand(1).getReg(); int64_t ImmValue = Inst.getOperand(2).getImm(); - bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue); + bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue)); unsigned FinalOpcode = Inst.getOpcode(); @@ -3530,30 +3833,69 @@ bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, switch (FinalOpcode) { default: llvm_unreachable("unimplemented expansion"); - case (Mips::ADDi): + case Mips::ADDi: FinalOpcode = Mips::ADD; break; - case (Mips::ADDiu): + case Mips::ADDiu: FinalOpcode = Mips::ADDu; break; - case (Mips::ANDi): + case Mips::ANDi: FinalOpcode = Mips::AND; break; - case (Mips::NORImm): + case Mips::NORImm: FinalOpcode = Mips::NOR; break; - case (Mips::ORi): + case Mips::ORi: FinalOpcode = Mips::OR; break; - case (Mips::SLTi): + case Mips::SLTi: FinalOpcode = Mips::SLT; break; - case (Mips::SLTiu): + case Mips::SLTiu: FinalOpcode = Mips::SLTu; break; - case (Mips::XORi): + case Mips::XORi: FinalOpcode = Mips::XOR; break; + case Mips::ADDi_MM: + FinalOpcode = Mips::ADD_MM; + break; + case Mips::ADDiu_MM: + FinalOpcode = Mips::ADDu_MM; + break; + case Mips::ANDi_MM: + FinalOpcode = Mips::AND_MM; + break; + case Mips::ORi_MM: + FinalOpcode = Mips::OR_MM; + break; + case Mips::SLTi_MM: + FinalOpcode = Mips::SLT_MM; + break; + case Mips::SLTiu_MM: + FinalOpcode = Mips::SLTu_MM; + break; + case Mips::XORi_MM: + FinalOpcode = Mips::XOR_MM; + break; + case Mips::ANDi64: + FinalOpcode = Mips::AND64; + break; + case Mips::NORImm64: + FinalOpcode = Mips::NOR64; + break; + case Mips::ORi64: + FinalOpcode = Mips::OR64; + break; + case Mips::SLTImm64: + FinalOpcode = Mips::SLT64; + break; + case Mips::SLTUImm64: + FinalOpcode = Mips::SLTu64; + break; + case Mips::XORi64: + FinalOpcode = Mips::XOR64; + break; } if (FinalDstReg == Mips::NoRegister) @@ -3578,7 +3920,6 @@ bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, unsigned SecondShift = Mips::NOP; if (hasMips32r2()) { - if (DReg == SReg) { TmpReg = getATReg(Inst.getLoc()); if (!TmpReg) @@ -3600,7 +3941,6 @@ bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, } if (hasMips32()) { - switch (Inst.getOpcode()) { default: llvm_unreachable("unexpected instruction opcode"); @@ -3642,7 +3982,6 @@ bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc, unsigned SecondShift = Mips::NOP; if (hasMips32r2()) { - if (Inst.getOpcode() == Mips::ROLImm) { uint64_t MaxShift = 32; uint64_t ShiftValue = ImmValue; @@ -3661,7 +4000,6 @@ bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc, } if (hasMips32()) { - if (ImmValue == 0) { TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI); return false; @@ -3707,7 +4045,6 @@ bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, unsigned SecondShift = Mips::NOP; if (hasMips64r2()) { - if (TmpReg == SReg) { TmpReg = getATReg(Inst.getLoc()); if (!TmpReg) @@ -3729,7 +4066,6 @@ bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, } if (hasMips64()) { - switch (Inst.getOpcode()) { default: llvm_unreachable("unexpected instruction opcode"); @@ -3773,7 +4109,6 @@ bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCInst TmpInst; if (hasMips64r2()) { - unsigned FinalOpcode = Mips::NOP; if (ImmValue == 0) FinalOpcode = Mips::DROTR; @@ -3801,7 +4136,6 @@ bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc, } if (hasMips64()) { - if (ImmValue == 0) { TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI); return false; @@ -3871,6 +4205,119 @@ bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, return false; } +bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI) { + MipsTargetStreamer &TOut = getTargetStreamer(); + unsigned ATReg = Mips::NoRegister; + unsigned DstReg = Inst.getOperand(0).getReg(); + unsigned SrcReg = Inst.getOperand(1).getReg(); + int32_t ImmValue = Inst.getOperand(2).getImm(); + + ATReg = getATReg(IDLoc); + if (!ATReg) + return true; + + loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out, STI); + + TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT, + SrcReg, ATReg, IDLoc, STI); + + TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI); + + return false; +} + +bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI) { + MipsTargetStreamer &TOut = getTargetStreamer(); + unsigned ATReg = Mips::NoRegister; + unsigned DstReg = Inst.getOperand(0).getReg(); + unsigned SrcReg = Inst.getOperand(1).getReg(); + unsigned TmpReg = Inst.getOperand(2).getReg(); + + ATReg = getATReg(Inst.getLoc()); + if (!ATReg) + return true; + + TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT, + SrcReg, TmpReg, IDLoc, STI); + + TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI); + + TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32, + DstReg, DstReg, 0x1F, IDLoc, STI); + + TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI); + + if (useTraps()) { + TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI); + } else { + MCContext & Context = TOut.getStreamer().getContext(); + MCSymbol * BrTarget = Context.createTempSymbol(); + MCOperand LabelOp = + MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context)); + + TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI); + if (AssemblerOptions.back()->isReorder()) + TOut.emitNop(IDLoc, STI); + TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI); + + TOut.getStreamer().EmitLabel(BrTarget); + } + TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI); + + return false; +} + +bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI) { + MipsTargetStreamer &TOut = getTargetStreamer(); + unsigned ATReg = Mips::NoRegister; + unsigned DstReg = Inst.getOperand(0).getReg(); + unsigned SrcReg = Inst.getOperand(1).getReg(); + unsigned TmpReg = Inst.getOperand(2).getReg(); + + ATReg = getATReg(IDLoc); + if (!ATReg) + return true; + + TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu, + SrcReg, TmpReg, IDLoc, STI); + + TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI); + TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI); + if (useTraps()) { + TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI); + } else { + MCContext & Context = TOut.getStreamer().getContext(); + MCSymbol * BrTarget = Context.createTempSymbol(); + MCOperand LabelOp = + MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context)); + + TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI); + if (AssemblerOptions.back()->isReorder()) + TOut.emitNop(IDLoc, STI); + TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI); + + TOut.getStreamer().EmitLabel(BrTarget); + } + + return false; +} + +bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI) { + MipsTargetStreamer &TOut = getTargetStreamer(); + unsigned DstReg = Inst.getOperand(0).getReg(); + unsigned SrcReg = Inst.getOperand(1).getReg(); + unsigned TmpReg = Inst.getOperand(2).getReg(); + + TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI); + TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI); + + return false; +} + static unsigned nextReg(unsigned Reg) { switch (Reg) { case Mips::ZERO: return Mips::AT; @@ -3985,7 +4432,6 @@ bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI) { - warnIfNoMacro(IDLoc); MipsTargetStreamer &TOut = getTargetStreamer(); @@ -4158,17 +4604,15 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, MCStreamer &Out, uint64_t &ErrorInfo, bool MatchingInlineAsm) { - MCInst Inst; unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm); switch (MatchResult) { - case Match_Success: { + case Match_Success: if (processInstruction(Inst, IDLoc, Out, STI)) return true; return false; - } case Match_MissingFeature: Error(IDLoc, "instruction requires a CPU feature not currently enabled"); return true; @@ -4441,7 +4885,6 @@ int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) { } int MipsAsmParser::matchFPURegisterName(StringRef Name) { - if (Name[0] == 'f') { StringRef NumString = Name.substr(1); unsigned IntVal; @@ -4455,7 +4898,6 @@ int MipsAsmParser::matchFPURegisterName(StringRef Name) { } int MipsAsmParser::matchFCCRegisterName(StringRef Name) { - if (Name.startswith("fcc")) { StringRef NumString = Name.substr(3); unsigned IntVal; @@ -4469,7 +4911,6 @@ int MipsAsmParser::matchFCCRegisterName(StringRef Name) { } int MipsAsmParser::matchACRegisterName(StringRef Name) { - if (Name.startswith("ac")) { StringRef NumString = Name.substr(2); unsigned IntVal; @@ -4511,6 +4952,10 @@ int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) { return CC; } +bool MipsAsmParser::canUseATReg() { + return AssemblerOptions.back()->getATRegIndex() != 0; +} + unsigned MipsAsmParser::getATReg(SMLoc Loc) { unsigned ATIndex = AssemblerOptions.back()->getATRegIndex(); if (ATIndex == 0) { @@ -4589,7 +5034,6 @@ bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { } bool MipsAsmParser::isEvaluated(const MCExpr *Expr) { - switch (Expr->getKind()) { case MCExpr::Constant: return true; @@ -5522,7 +5966,7 @@ bool MipsAsmParser::parseSetPushDirective() { // Create a copy of the current assembler options environment and push it. AssemblerOptions.push_back( - make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get())); + llvm::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get())); getTargetStreamer().emitDirectiveSetPush(); return false; @@ -5914,6 +6358,14 @@ bool MipsAsmParser::parseDirectiveSet() { return parseSetAtDirective(); } else if (Tok.getString() == "arch") { return parseSetArchDirective(); + } else if (Tok.getString() == "bopt") { + Warning(Tok.getLoc(), "'bopt' feature is unsupported"); + getParser().Lex(); + return false; + } else if (Tok.getString() == "nobopt") { + // We're already running in nobopt mode, so nothing to do. + getParser().Lex(); + return false; } else if (Tok.getString() == "fp") { return parseSetFpDirective(); } else if (Tok.getString() == "oddspreg") { @@ -6001,7 +6453,7 @@ bool MipsAsmParser::parseDirectiveSet() { bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) { MCAsmParser &Parser = getParser(); if (getLexer().isNot(AsmToken::EndOfStatement)) { - for (;;) { + while (true) { const MCExpr *Value; if (getParser().parseExpression(Value)) return true; @@ -6773,3 +7225,15 @@ extern "C" void LLVMInitializeMipsAsmParser() { #define GET_REGISTER_MATCHER #define GET_MATCHER_IMPLEMENTATION #include "MipsGenAsmMatcher.inc" + +bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) { + // Find the appropriate table for this asm variant. + const MatchEntry *Start, *End; + switch (VariantID) { + default: llvm_unreachable("invalid variant!"); + case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break; + } + // Search the table. + auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode()); + return MnemonicRange.first != MnemonicRange.second; +} diff --git a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp index f80efb18507b..ecdf6b0de6e7 100644 --- a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -1,4 +1,4 @@ -//===- MipsDisassembler.cpp - Disassembler for Mips -------------*- C++ -*-===// +//===- MipsDisassembler.cpp - Disassembler for Mips -----------------------===// // // The LLVM Compiler Infrastructure // @@ -12,15 +12,21 @@ //===----------------------------------------------------------------------===// #include "Mips.h" -#include "MipsRegisterInfo.h" -#include "MipsSubtarget.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCDisassembler/MCDisassembler.h" #include "llvm/MC/MCFixedLenDisassembler.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Support/TargetRegistry.h" +#include <cassert> +#include <cstdint> using namespace llvm; @@ -33,6 +39,7 @@ namespace { class MipsDisassembler : public MCDisassembler { bool IsMicroMips; bool IsBigEndian; + public: MipsDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, bool IsBigEndian) : MCDisassembler(STI, Ctx), @@ -42,9 +49,11 @@ public: bool hasMips2() const { return STI.getFeatureBits()[Mips::FeatureMips2]; } bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; } bool hasMips32() const { return STI.getFeatureBits()[Mips::FeatureMips32]; } + bool hasMips32r6() const { return STI.getFeatureBits()[Mips::FeatureMips32r6]; } + bool isFP64() const { return STI.getFeatureBits()[Mips::FeatureFP64Bit]; } bool isGP64() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; } @@ -527,11 +536,13 @@ static DecodeStatus DecodeMovePRegPair(MCInst &Inst, unsigned Insn, const void *Decoder); namespace llvm { + Target &getTheMipselTarget(); Target &getTheMipsTarget(); Target &getTheMips64Target(); Target &getTheMips64elTarget(); -} + +} // end namespace llvm static MCDisassembler *createMipsDisassembler( const Target &T, @@ -1106,6 +1117,7 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, raw_ostream &CStream) const { uint32_t Insn; DecodeStatus Result; + Size = 0; if (IsMicroMips) { Result = readInstruction16(Bytes, Address, Size, Insn, IsBigEndian); @@ -1168,98 +1180,88 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, } } - // This is an invalid instruction. Let the disassembler move forward by the - // minimum instruction size. + // This is an invalid instruction. Claim that the Size is 2 bytes. Since + // microMIPS instructions have a minimum alignment of 2, the next 2 bytes + // could form a valid instruction. The two bytes we rejected as an + // instruction could have actually beeen an inline constant pool that is + // unconditionally branched over. Size = 2; return MCDisassembler::Fail; } + // Attempt to read the instruction so that we can attempt to decode it. If + // the buffer is not 4 bytes long, let the higher level logic figure out + // what to do with a size of zero and MCDisassembler::Fail. Result = readInstruction32(Bytes, Address, Size, Insn, IsBigEndian, false); - if (Result == MCDisassembler::Fail) { - Size = 4; + if (Result == MCDisassembler::Fail) return MCDisassembler::Fail; - } + + // The only instruction size for standard encoded MIPS. + Size = 4; if (hasCOP3()) { DEBUG(dbgs() << "Trying COP3_ table (32-bit opcodes):\n"); Result = decodeInstruction(DecoderTableCOP3_32, Instr, Insn, Address, this, STI); - if (Result != MCDisassembler::Fail) { - Size = 4; + if (Result != MCDisassembler::Fail) return Result; - } } if (hasMips32r6() && isGP64()) { DEBUG(dbgs() << "Trying Mips32r6_64r6 (GPR64) table (32-bit opcodes):\n"); Result = decodeInstruction(DecoderTableMips32r6_64r6_GP6432, Instr, Insn, Address, this, STI); - if (Result != MCDisassembler::Fail) { - Size = 4; + if (Result != MCDisassembler::Fail) return Result; - } } if (hasMips32r6() && isPTR64()) { DEBUG(dbgs() << "Trying Mips32r6_64r6 (PTR64) table (32-bit opcodes):\n"); Result = decodeInstruction(DecoderTableMips32r6_64r6_PTR6432, Instr, Insn, Address, this, STI); - if (Result != MCDisassembler::Fail) { - Size = 4; + if (Result != MCDisassembler::Fail) return Result; - } } if (hasMips32r6()) { DEBUG(dbgs() << "Trying Mips32r6_64r6 table (32-bit opcodes):\n"); Result = decodeInstruction(DecoderTableMips32r6_64r632, Instr, Insn, Address, this, STI); - if (Result != MCDisassembler::Fail) { - Size = 4; + if (Result != MCDisassembler::Fail) return Result; - } } if (hasMips2() && isPTR64()) { DEBUG(dbgs() << "Trying Mips32r6_64r6 (PTR64) table (32-bit opcodes):\n"); Result = decodeInstruction(DecoderTableMips32_64_PTR6432, Instr, Insn, Address, this, STI); - if (Result != MCDisassembler::Fail) { - Size = 4; + if (Result != MCDisassembler::Fail) return Result; - } } if (hasCnMips()) { DEBUG(dbgs() << "Trying CnMips table (32-bit opcodes):\n"); Result = decodeInstruction(DecoderTableCnMips32, Instr, Insn, Address, this, STI); - if (Result != MCDisassembler::Fail) { - Size = 4; + if (Result != MCDisassembler::Fail) return Result; - } } if (isGP64()) { DEBUG(dbgs() << "Trying Mips64 (GPR64) table (32-bit opcodes):\n"); Result = decodeInstruction(DecoderTableMips6432, Instr, Insn, Address, this, STI); - if (Result != MCDisassembler::Fail) { - Size = 4; + if (Result != MCDisassembler::Fail) return Result; - } } DEBUG(dbgs() << "Trying Mips table (32-bit opcodes):\n"); // Calling the auto-generated decoder function. Result = decodeInstruction(DecoderTableMips32, Instr, Insn, Address, this, STI); - if (Result != MCDisassembler::Fail) { - Size = 4; + if (Result != MCDisassembler::Fail) return Result; - } - Size = 4; return MCDisassembler::Fail; } @@ -1267,16 +1269,13 @@ static DecodeStatus DecodeCPU16RegsRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { - return MCDisassembler::Fail; - } static DecodeStatus DecodeGPR64RegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { - if (RegNo > 31) return MCDisassembler::Fail; @@ -1620,7 +1619,7 @@ static DecodeStatus DecodeMSA128Mem(MCInst &Inst, unsigned Insn, switch(Inst.getOpcode()) { default: - assert (0 && "Unexpected instruction"); + assert(false && "Unexpected instruction"); return MCDisassembler::Fail; break; case Mips::LD_B: @@ -1980,7 +1979,6 @@ static DecodeStatus DecodeAFGR64RegisterClass(MCInst &Inst, if (RegNo > 30 || RegNo %2) return MCDisassembler::Fail; - ; unsigned Reg = getReg(Decoder, Mips::AFGR64RegClassID, RegNo /2); Inst.addOperand(MCOperand::createReg(Reg)); return MCDisassembler::Success; @@ -2128,7 +2126,6 @@ static DecodeStatus DecodeJumpTarget(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { - unsigned JumpOffset = fieldFromInstruction(Insn, 0, 26) << 2; Inst.addOperand(MCOperand::createImm(JumpOffset)); return MCDisassembler::Success; @@ -2267,7 +2264,14 @@ static DecodeStatus DecodeInsSize(MCInst &Inst, const void *Decoder) { // First we need to grab the pos(lsb) from MCInst. int Pos = Inst.getOperand(2).getImm(); - int Size = (int) Insn - Pos + 1; + if (Inst.getOpcode() == Mips::DINSU) + Pos += 32; + int Size; + if (Inst.getOpcode() == Mips::DINSM || + Inst.getOpcode() == Mips::DINSU) + Size = (int) Insn - Pos + 33; + else + Size = (int) Insn - Pos + 1; Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Size))); return MCDisassembler::Success; } @@ -2363,7 +2367,6 @@ static DecodeStatus DecodeRegListOperand16(MCInst &Inst, unsigned Insn, static DecodeStatus DecodeMovePRegPair(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { - unsigned RegPair = fieldFromInstruction(Insn, 7, 3); switch (RegPair) { diff --git a/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp b/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp index 932d38a0b9fe..4a2b75b9ae46 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp @@ -1,4 +1,4 @@ -//===-- MipsABIFlagsSection.cpp - Mips ELF ABI Flags Section ---*- C++ -*--===// +//===- MipsABIFlagsSection.cpp - Mips ELF ABI Flags Section ---------------===// // // The LLVM Compiler Infrastructure // @@ -7,7 +7,11 @@ // //===----------------------------------------------------------------------===// -#include "MipsABIFlagsSection.h" +#include "MCTargetDesc/MipsABIFlagsSection.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MipsABIFlags.h" using namespace llvm; @@ -51,6 +55,7 @@ uint8_t MipsABIFlagsSection::getCPR1SizeValue() { } namespace llvm { + MCStreamer &operator<<(MCStreamer &OS, MipsABIFlagsSection &ABIFlagsSection) { // Write out a Elf_Internal_ABIFlags_v0 struct OS.EmitIntValue(ABIFlagsSection.getVersionValue(), 2); // version @@ -66,4 +71,5 @@ MCStreamer &operator<<(MCStreamer &OS, MipsABIFlagsSection &ABIFlagsSection) { OS.EmitIntValue(ABIFlagsSection.getFlags2Value(), 4); // flags2 return OS; } -} + +} // end namespace llvm diff --git a/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h b/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h index 3966cae9fe33..f38541027023 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h +++ b/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h @@ -1,4 +1,4 @@ -//===-- MipsABIFlagsSection.h - Mips ELF ABI Flags Section -----*- C++ -*--===// +//===- MipsABIFlagsSection.h - Mips ELF ABI Flags Section -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -10,9 +10,10 @@ #ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIFLAGSSECTION_H #define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIFLAGSSECTION_H -#include "llvm/MC/MCStreamer.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MipsABIFlags.h" +#include <cstdint> namespace llvm { @@ -23,36 +24,32 @@ struct MipsABIFlagsSection { enum class FpABIKind { ANY, XX, S32, S64, SOFT }; // Version of flags structure. - uint16_t Version; + uint16_t Version = 0; // The level of the ISA: 1-5, 32, 64. - uint8_t ISALevel; + uint8_t ISALevel = 0; // The revision of ISA: 0 for MIPS V and below, 1-n otherwise. - uint8_t ISARevision; + uint8_t ISARevision = 0; // The size of general purpose registers. - Mips::AFL_REG GPRSize; + Mips::AFL_REG GPRSize = Mips::AFL_REG_NONE; // The size of co-processor 1 registers. - Mips::AFL_REG CPR1Size; + Mips::AFL_REG CPR1Size = Mips::AFL_REG_NONE; // The size of co-processor 2 registers. - Mips::AFL_REG CPR2Size; + Mips::AFL_REG CPR2Size = Mips::AFL_REG_NONE; // Processor-specific extension. - Mips::AFL_EXT ISAExtension; + Mips::AFL_EXT ISAExtension = Mips::AFL_EXT_NONE; // Mask of ASEs used. - uint32_t ASESet; + uint32_t ASESet = 0; - bool OddSPReg; + bool OddSPReg = false; - bool Is32BitABI; + bool Is32BitABI = false; protected: // The floating-point ABI. - FpABIKind FpABI; + FpABIKind FpABI = FpABIKind::ANY; public: - MipsABIFlagsSection() - : Version(0), ISALevel(0), ISARevision(0), GPRSize(Mips::AFL_REG_NONE), - CPR1Size(Mips::AFL_REG_NONE), CPR2Size(Mips::AFL_REG_NONE), - ISAExtension(Mips::AFL_EXT_NONE), ASESet(0), OddSPReg(false), - Is32BitABI(false), FpABI(FpABIKind::ANY) {} + MipsABIFlagsSection() = default; uint16_t getVersionValue() { return (uint16_t)Version; } uint8_t getISALevelValue() { return (uint8_t)ISALevel; } @@ -80,6 +77,7 @@ public: FpABI = Value; Is32BitABI = IsABI32Bit; } + StringRef getFpABIString(FpABIKind Value); template <class PredicateLibrary> @@ -195,6 +193,7 @@ public: }; MCStreamer &operator<<(MCStreamer &OS, MipsABIFlagsSection &ABIFlagsSection); -} -#endif +} // end namespace llvm + +#endif // LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIFLAGSSECTION_H diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp index 38b11f78e36d..3304449efb91 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp @@ -34,7 +34,7 @@ using namespace llvm; // Prepare value for the target space for it static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, - MCContext *Ctx = nullptr) { + MCContext &Ctx) { unsigned Kind = Fixup.getKind(); @@ -74,8 +74,8 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, // address range. Forcing a signed division because Value can be negative. Value = (int64_t)Value / 4; // We now check if Value can be encoded as a 16-bit signed immediate. - if (!isInt<16>(Value) && Ctx) { - Ctx->reportError(Fixup.getLoc(), "out of range PC16 fixup"); + if (!isInt<16>(Value)) { + Ctx.reportError(Fixup.getLoc(), "out of range PC16 fixup"); return 0; } break; @@ -84,8 +84,8 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, // Forcing a signed division because Value can be negative. Value = (int64_t)Value / 4; // We now check if Value can be encoded as a 19-bit signed immediate. - if (!isInt<19>(Value) && Ctx) { - Ctx->reportError(Fixup.getLoc(), "out of range PC19 fixup"); + if (!isInt<19>(Value)) { + Ctx.reportError(Fixup.getLoc(), "out of range PC19 fixup"); return 0; } break; @@ -121,8 +121,8 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, // Forcing a signed division because Value can be negative. Value = (int64_t) Value / 2; // We now check if Value can be encoded as a 7-bit signed immediate. - if (!isInt<7>(Value) && Ctx) { - Ctx->reportError(Fixup.getLoc(), "out of range PC7 fixup"); + if (!isInt<7>(Value)) { + Ctx.reportError(Fixup.getLoc(), "out of range PC7 fixup"); return 0; } break; @@ -131,8 +131,8 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, // Forcing a signed division because Value can be negative. Value = (int64_t) Value / 2; // We now check if Value can be encoded as a 10-bit signed immediate. - if (!isInt<10>(Value) && Ctx) { - Ctx->reportError(Fixup.getLoc(), "out of range PC10 fixup"); + if (!isInt<10>(Value)) { + Ctx.reportError(Fixup.getLoc(), "out of range PC10 fixup"); return 0; } break; @@ -141,8 +141,8 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, // Forcing a signed division because Value can be negative. Value = (int64_t)Value / 2; // We now check if Value can be encoded as a 16-bit signed immediate. - if (!isInt<16>(Value) && Ctx) { - Ctx->reportError(Fixup.getLoc(), "out of range PC16 fixup"); + if (!isInt<16>(Value)) { + Ctx.reportError(Fixup.getLoc(), "out of range PC16 fixup"); return 0; } break; @@ -150,21 +150,21 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, // Forcing a signed division because Value can be negative. Value = (int64_t)Value / 8; // We now check if Value can be encoded as a 18-bit signed immediate. - if (!isInt<18>(Value) && Ctx) { - Ctx->reportError(Fixup.getLoc(), "out of range PC18 fixup"); + if (!isInt<18>(Value)) { + Ctx.reportError(Fixup.getLoc(), "out of range PC18 fixup"); return 0; } break; case Mips::fixup_MICROMIPS_PC18_S3: // Check alignment. - if ((Value & 7) && Ctx) { - Ctx->reportError(Fixup.getLoc(), "out of range PC18 fixup"); + if ((Value & 7)) { + Ctx.reportError(Fixup.getLoc(), "out of range PC18 fixup"); } // Forcing a signed division because Value can be negative. Value = (int64_t)Value / 8; // We now check if Value can be encoded as a 18-bit signed immediate. - if (!isInt<18>(Value) && Ctx) { - Ctx->reportError(Fixup.getLoc(), "out of range PC18 fixup"); + if (!isInt<18>(Value)) { + Ctx.reportError(Fixup.getLoc(), "out of range PC18 fixup"); return 0; } break; @@ -172,8 +172,8 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, // Forcing a signed division because Value can be negative. Value = (int64_t) Value / 4; // We now check if Value can be encoded as a 21-bit signed immediate. - if (!isInt<21>(Value) && Ctx) { - Ctx->reportError(Fixup.getLoc(), "out of range PC21 fixup"); + if (!isInt<21>(Value)) { + Ctx.reportError(Fixup.getLoc(), "out of range PC21 fixup"); return 0; } break; @@ -181,8 +181,8 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, // Forcing a signed division because Value can be negative. Value = (int64_t) Value / 4; // We now check if Value can be encoded as a 26-bit signed immediate. - if (!isInt<26>(Value) && Ctx) { - Ctx->reportError(Fixup.getLoc(), "out of range PC26 fixup"); + if (!isInt<26>(Value)) { + Ctx.reportError(Fixup.getLoc(), "out of range PC26 fixup"); return 0; } break; @@ -190,8 +190,8 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, // Forcing a signed division because Value can be negative. Value = (int64_t)Value / 2; // We now check if Value can be encoded as a 26-bit signed immediate. - if (!isInt<26>(Value) && Ctx) { - Ctx->reportFatalError(Fixup.getLoc(), "out of range PC26 fixup"); + if (!isInt<26>(Value)) { + Ctx.reportFatalError(Fixup.getLoc(), "out of range PC26 fixup"); return 0; } break; @@ -199,8 +199,8 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, // Forcing a signed division because Value can be negative. Value = (int64_t)Value / 2; // We now check if Value can be encoded as a 21-bit signed immediate. - if (!isInt<21>(Value) && Ctx) { - Ctx->reportError(Fixup.getLoc(), "out of range PC21 fixup"); + if (!isInt<21>(Value)) { + Ctx.reportError(Fixup.getLoc(), "out of range PC21 fixup"); return 0; } break; @@ -236,10 +236,10 @@ static unsigned calculateMMLEIndex(unsigned i) { /// data fragment, at the offset specified by the fixup and following the /// fixup kind as appropriate. void MipsAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, - unsigned DataSize, uint64_t Value, - bool IsPCRel) const { + unsigned DataSize, uint64_t Value, bool IsPCRel, + MCContext &Ctx) const { MCFixupKind Kind = Fixup.getKind(); - Value = adjustFixupValue(Fixup, Value); + Value = adjustFixupValue(Fixup, Value, Ctx); if (!Value) return; // Doesn't change encoding. @@ -471,24 +471,6 @@ bool MipsAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { return true; } -/// processFixupValue - Target hook to process the literal value of a fixup -/// if necessary. -void MipsAsmBackend::processFixupValue(const MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFixup &Fixup, - const MCFragment *DF, - const MCValue &Target, - uint64_t &Value, - bool &IsResolved) { - // At this point we'll ignore the value returned by adjustFixupValue as - // we are only checking if the fixup can be applied correctly. We have - // access to MCContext from here which allows us to report a fatal error - // with *possibly* a source code location. - // The caller will also ignore any changes we make to Value - // (recordRelocation() overwrites it with it's own calculation). - (void)adjustFixupValue(Fixup, Value, &Asm.getContext()); -} - // MCAsmBackend MCAsmBackend *llvm::createMipsAsmBackendEL32(const Target &T, const MCRegisterInfo &MRI, diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h index f260cfa566c9..4b3cc6e21f4c 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h +++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h @@ -39,7 +39,7 @@ public: MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override; void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, - uint64_t Value, bool IsPCRel) const override; + uint64_t Value, bool IsPCRel, MCContext &Ctx) const override; Optional<MCFixupKind> getFixupKind(StringRef Name) const override; const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override; @@ -82,11 +82,6 @@ public: bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override; - void processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout, - const MCFixup &Fixup, const MCFragment *DF, - const MCValue &Target, uint64_t &Value, - bool &IsResolved) override; - }; // class MipsAsmBackend } // namespace diff --git a/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp index b2efd726da53..324fd3c6fe14 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp @@ -7,33 +7,38 @@ // //===----------------------------------------------------------------------===// -#include <algorithm> -#include <list> -#include "MCTargetDesc/MipsBaseInfo.h" #include "MCTargetDesc/MipsFixupKinds.h" -#include "MCTargetDesc/MipsMCExpr.h" #include "MCTargetDesc/MipsMCTargetDesc.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCELFObjectWriter.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCFixup.h" #include "llvm/MC/MCSymbolELF.h" -#include "llvm/MC/MCValue.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ELF.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <cstdint> +#include <iterator> +#include <list> +#include <utility> #define DEBUG_TYPE "mips-elf-object-writer" using namespace llvm; namespace { + /// Holds additional information needed by the relocation ordering algorithm. struct MipsRelocationEntry { const ELFRelocationEntry R; ///< The relocation. - bool Matched; ///< Is this relocation part of a match. + bool Matched = false; ///< Is this relocation part of a match. - MipsRelocationEntry(const ELFRelocationEntry &R) : R(R), Matched(false) {} + MipsRelocationEntry(const ELFRelocationEntry &R) : R(R) {} void print(raw_ostream &Out) const { R.print(Out); @@ -53,23 +58,33 @@ public: MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, bool _isN64, bool IsLittleEndian); - ~MipsELFObjectWriter() override; + ~MipsELFObjectWriter() override = default; unsigned getRelocType(MCContext &Ctx, const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const override; bool needsRelocateWithSymbol(const MCSymbol &Sym, unsigned Type) const override; - virtual void sortRelocs(const MCAssembler &Asm, - std::vector<ELFRelocationEntry> &Relocs) override; + void sortRelocs(const MCAssembler &Asm, + std::vector<ELFRelocationEntry> &Relocs) override; +}; + +/// The possible results of the Predicate function used by find_best. +enum FindBestPredicateResult { + FindBest_NoMatch = 0, ///< The current element is not a match. + FindBest_Match, ///< The current element is a match but better ones are + /// possible. + FindBest_PerfectMatch, ///< The current element is an unbeatable match. }; +} // end anonymous namespace + /// Copy elements in the range [First, Last) to d1 when the predicate is true or /// d2 when the predicate is false. This is essentially both std::copy_if and /// std::remove_copy_if combined into a single pass. template <class InputIt, class OutputIt1, class OutputIt2, class UnaryPredicate> -std::pair<OutputIt1, OutputIt2> copy_if_else(InputIt First, InputIt Last, - OutputIt1 d1, OutputIt2 d2, - UnaryPredicate Predicate) { +static std::pair<OutputIt1, OutputIt2> copy_if_else(InputIt First, InputIt Last, + OutputIt1 d1, OutputIt2 d2, + UnaryPredicate Predicate) { for (InputIt I = First; I != Last; ++I) { if (Predicate(*I)) { *d1 = *I; @@ -83,14 +98,6 @@ std::pair<OutputIt1, OutputIt2> copy_if_else(InputIt First, InputIt Last, return std::make_pair(d1, d2); } -/// The possible results of the Predicate function used by find_best. -enum FindBestPredicateResult { - FindBest_NoMatch = 0, ///< The current element is not a match. - FindBest_Match, ///< The current element is a match but better ones are - /// possible. - FindBest_PerfectMatch, ///< The current element is an unbeatable match. -}; - /// Find the best match in the range [First, Last). /// /// An element matches when Predicate(X) returns FindBest_Match or @@ -101,8 +108,8 @@ enum FindBestPredicateResult { /// This is similar to std::find_if but finds the best of multiple possible /// matches. template <class InputIt, class UnaryPredicate, class Comparator> -InputIt find_best(InputIt First, InputIt Last, UnaryPredicate Predicate, - Comparator BetterThan) { +static InputIt find_best(InputIt First, InputIt Last, UnaryPredicate Predicate, + Comparator BetterThan) { InputIt Best = Last; for (InputIt I = First; I != Last; ++I) { @@ -202,16 +209,12 @@ static void dumpRelocs(const char *Prefix, const Container &Relocs) { } #endif -} // end anonymous namespace - MipsELFObjectWriter::MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, bool _isN64, bool IsLittleEndian) : MCELFObjectTargetWriter(_is64Bit, OSABI, ELF::EM_MIPS, /*HasRelocationAddend*/ _isN64, /*IsN64*/ _isN64) {} -MipsELFObjectWriter::~MipsELFObjectWriter() {} - unsigned MipsELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target, const MCFixup &Fixup, @@ -419,7 +422,6 @@ unsigned MipsELFObjectWriter::getRelocType(MCContext &Ctx, /// always match using the expressions from the source. void MipsELFObjectWriter::sortRelocs(const MCAssembler &Asm, std::vector<ELFRelocationEntry> &Relocs) { - // We do not need to sort the relocation table for RELA relocations which // N32/N64 uses as the relocation addend contains the value we require, // rather than it being split across a pair of relocations. @@ -524,6 +526,8 @@ bool MipsELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym, case ELF::R_MIPS_GOT16: case ELF::R_MIPS16_GOT16: case ELF::R_MICROMIPS_GOT16: + case ELF::R_MIPS_HIGHER: + case ELF::R_MIPS_HIGHEST: case ELF::R_MIPS_HI16: case ELF::R_MIPS16_HI16: case ELF::R_MICROMIPS_HI16: @@ -567,8 +571,6 @@ bool MipsELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym, case ELF::R_MIPS_INSERT_A: case ELF::R_MIPS_INSERT_B: case ELF::R_MIPS_DELETE: - case ELF::R_MIPS_HIGHER: - case ELF::R_MIPS_HIGHEST: case ELF::R_MIPS_CALL_HI16: case ELF::R_MIPS_CALL_LO16: case ELF::R_MIPS_SCN_DISP: diff --git a/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp b/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp index e7d687e89a8a..ae3278322311 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp @@ -8,15 +8,19 @@ //===----------------------------------------------------------------------===// #include "MipsELFStreamer.h" +#include "MipsOptionRecord.h" #include "MipsTargetStreamer.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCSymbolELF.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/ELF.h" using namespace llvm; void MipsELFStreamer::EmitInstruction(const MCInst &Inst, - const MCSubtargetInfo &STI) { + const MCSubtargetInfo &STI, bool) { MCELFStreamer::EmitInstruction(Inst, STI); MCContext &Context = getContext(); @@ -51,7 +55,7 @@ void MipsELFStreamer::createPendingLabelRelocs() { Labels.clear(); } -void MipsELFStreamer::EmitLabel(MCSymbol *Symbol) { +void MipsELFStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) { MCELFStreamer::EmitLabel(Symbol); Labels.push_back(Symbol); } diff --git a/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h b/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h index a241cdebdcc8..f5eda112817e 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h +++ b/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h @@ -1,4 +1,4 @@ -//===-------- MipsELFStreamer.h - ELF Object Output -----------------------===// +//===- MipsELFStreamer.h - ELF Object Output --------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -21,6 +21,7 @@ #include <memory> namespace llvm { + class MCAsmBackend; class MCCodeEmitter; class MCContext; @@ -31,12 +32,10 @@ class MipsELFStreamer : public MCELFStreamer { MipsRegInfoRecord *RegInfoRecord; SmallVector<MCSymbol*, 4> Labels; - public: MipsELFStreamer(MCContext &Context, MCAsmBackend &MAB, raw_pwrite_stream &OS, MCCodeEmitter *Emitter) : MCELFStreamer(Context, MAB, OS, Emitter) { - RegInfoRecord = new MipsRegInfoRecord(this, Context); MipsOptionRecords.push_back( std::unique_ptr<MipsRegInfoRecord>(RegInfoRecord)); @@ -46,12 +45,13 @@ public: /// \p Inst is actually emitted. For example, we can inspect the operands and /// gather sufficient information that allows us to reason about the register /// usage for the translation unit. - void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override; + void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, + bool = false) override; /// Overriding this function allows us to record all labels that should be /// marked as microMIPS. Based on this data marking is done in /// EmitInstruction. - void EmitLabel(MCSymbol *Symbol) override; + void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override; /// Overriding this function allows us to dismiss all labels that are /// candidates for marking as microMIPS when .section directive is processed. @@ -72,5 +72,6 @@ public: MCELFStreamer *createMipsELFStreamer(MCContext &Context, MCAsmBackend &MAB, raw_pwrite_stream &OS, MCCodeEmitter *Emitter, bool RelaxAll); -} // namespace llvm. -#endif +} // end namespace llvm + +#endif // LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSELFSTREAMER_H diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp index a44a35f49e5f..ebe3c5784888 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp @@ -19,9 +19,7 @@ using namespace llvm; void MipsMCAsmInfo::anchor() { } MipsMCAsmInfo::MipsMCAsmInfo(const Triple &TheTriple) { - if ((TheTriple.getArch() == Triple::mips) || - (TheTriple.getArch() == Triple::mips64)) - IsLittleEndian = false; + IsLittleEndian = TheTriple.isLittleEndian(); if ((TheTriple.getArch() == Triple::mips64el) || (TheTriple.getArch() == Triple::mips64)) { diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index 0614316d5ac7..5685f0426e9b 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -10,22 +10,29 @@ // This file implements the MipsMCCodeEmitter class. // //===----------------------------------------------------------------------===// -// -#include "MipsMCCodeEmitter.h" #include "MCTargetDesc/MipsFixupKinds.h" #include "MCTargetDesc/MipsMCExpr.h" #include "MCTargetDesc/MipsMCTargetDesc.h" +#include "MipsMCCodeEmitter.h" #include "llvm/ADT/APFloat.h" +#include "llvm/ADT/APInt.h" #include "llvm/ADT/SmallVector.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCFixup.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstrDesc.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <cstdint> + +using namespace llvm; #define DEBUG_TYPE "mccodeemitter" @@ -34,6 +41,7 @@ #undef GET_INSTRMAP_INFO namespace llvm { + MCCodeEmitter *createMipsMCCodeEmitterEB(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, MCContext &Ctx) { @@ -45,12 +53,12 @@ MCCodeEmitter *createMipsMCCodeEmitterEL(const MCInstrInfo &MCII, MCContext &Ctx) { return new MipsMCCodeEmitter(MCII, Ctx, true); } -} // End of namespace llvm. + +} // end namespace llvm // If the D<shift> instruction has a shift amount that is greater // than 31 (checked in calling routine), lower it to a D<shift>32 instruction static void LowerLargeShift(MCInst& Inst) { - assert(Inst.getNumOperands() == 3 && "Invalid no. of operands for shift!"); assert(Inst.getOperand(2).isImm()); @@ -103,24 +111,25 @@ static void LowerDins(MCInst& InstIn) { assert(InstIn.getOperand(3).isImm()); int64_t size = InstIn.getOperand(3).getImm(); - if (size <= 32) { - if (pos < 32) // DINS, do nothing - return; + assert((pos + size) <= 64 && + "DINS cannot have position plus size over 64"); + if (pos < 32) { + if ((pos + size) > 0 && (pos + size) <= 32) + return; // DINS, do nothing + else if ((pos + size) > 32) { + //DINSM + InstIn.getOperand(3).setImm(size - 32); + InstIn.setOpcode(Mips::DINSM); + } + } else if ((pos + size) > 32 && (pos + size) <= 64) { // DINSU InstIn.getOperand(2).setImm(pos - 32); InstIn.setOpcode(Mips::DINSU); - return; } - // DINSM - assert(pos < 32 && "DINS cannot have both size and pos > 32"); - InstIn.getOperand(3).setImm(size - 32); - InstIn.setOpcode(Mips::DINSM); - return; } // Fix a bad compact branch encoding for beqc/bnec. void MipsMCCodeEmitter::LowerCompactBranch(MCInst& Inst) const { - // Encoding may be illegal !(rs < rt), but this situation is // easily fixed. unsigned RegOp0 = Inst.getOperand(0).getReg(); @@ -146,7 +155,6 @@ void MipsMCCodeEmitter::LowerCompactBranch(MCInst& Inst) const { Inst.getOperand(0).setReg(RegOp1); Inst.getOperand(1).setReg(RegOp0); - } bool MipsMCCodeEmitter::isMicroMips(const MCSubtargetInfo &STI) const { @@ -186,7 +194,6 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { - // Non-pseudo instructions that get changed for direct object // only based on operand values. // If this list of instructions get much longer we will move @@ -272,7 +279,6 @@ unsigned MipsMCCodeEmitter:: getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); // If the destination is an immediate, divide by 4. @@ -295,7 +301,6 @@ unsigned MipsMCCodeEmitter:: getBranchTargetOpValue1SImm16(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); // If the destination is an immediate, divide by 2. @@ -318,7 +323,6 @@ unsigned MipsMCCodeEmitter:: getBranchTargetOpValueMMR6(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); // If the destination is an immediate, divide by 2. @@ -342,7 +346,6 @@ unsigned MipsMCCodeEmitter:: getBranchTargetOpValueLsl2MMR6(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); // If the destination is an immediate, divide by 4. @@ -366,7 +369,6 @@ unsigned MipsMCCodeEmitter:: getBranchTarget7OpValueMM(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); // If the destination is an immediate, divide by 2. @@ -388,7 +390,6 @@ unsigned MipsMCCodeEmitter:: getBranchTargetOpValueMMPC10(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); // If the destination is an immediate, divide by 2. @@ -410,7 +411,6 @@ unsigned MipsMCCodeEmitter:: getBranchTargetOpValueMM(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); // If the destination is an immediate, divide by 2. @@ -433,7 +433,6 @@ unsigned MipsMCCodeEmitter:: getBranchTarget21OpValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); // If the destination is an immediate, divide by 4. @@ -456,7 +455,6 @@ unsigned MipsMCCodeEmitter:: getBranchTarget21OpValueMM(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); // If the destination is an immediate, divide by 4. @@ -479,7 +477,6 @@ unsigned MipsMCCodeEmitter:: getBranchTarget26OpValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); // If the destination is an immediate, divide by 4. @@ -501,7 +498,6 @@ getBranchTarget26OpValue(const MCInst &MI, unsigned OpNo, unsigned MipsMCCodeEmitter::getBranchTarget26OpValueMM( const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); // If the destination is an immediate, divide by 2. @@ -525,7 +521,6 @@ unsigned MipsMCCodeEmitter:: getJumpOffset16OpValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); if (MO.isImm()) return MO.getImm(); @@ -544,7 +539,6 @@ unsigned MipsMCCodeEmitter:: getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); // If the destination is an immediate, divide by 4. if (MO.isImm()) return MO.getImm()>>2; @@ -562,7 +556,6 @@ unsigned MipsMCCodeEmitter:: getJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); // If the destination is an immediate, divide by 2. if (MO.isImm()) return MO.getImm() >> 1; @@ -580,7 +573,6 @@ unsigned MipsMCCodeEmitter:: getUImm5Lsl2Encoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); if (MO.isImm()) { // The immediate is encoded as 'immediate << 2'. @@ -599,7 +591,6 @@ unsigned MipsMCCodeEmitter:: getSImm3Lsa2Value(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); if (MO.isImm()) { int Value = MO.getImm(); @@ -613,7 +604,6 @@ unsigned MipsMCCodeEmitter:: getUImm6Lsl2Encoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); if (MO.isImm()) { unsigned Value = MO.getImm(); @@ -627,7 +617,6 @@ unsigned MipsMCCodeEmitter:: getSImm9AddiuspValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); if (MO.isImm()) { unsigned Binary = (MO.getImm() >> 2) & 0x0000ffff; @@ -711,7 +700,7 @@ getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups, case MipsMCExpr::MEK_GPREL: FixupKind = Mips::fixup_Mips_GPREL16; break; - case MipsMCExpr::MEK_LO: { + case MipsMCExpr::MEK_LO: // Check for %lo(%neg(%gp_rel(X))) if (MipsExpr->isGpOff()) { FixupKind = Mips::fixup_Mips_GPOFF_LO; @@ -720,7 +709,6 @@ getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups, FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16 : Mips::fixup_Mips_LO16; break; - } case MipsMCExpr::MEK_HIGHEST: FixupKind = Mips::fixup_Mips_HIGHEST; break; diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h index 2d041dcbf040..d12d3195521a 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h +++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h @@ -1,4 +1,4 @@ -//===-- MipsMCCodeEmitter.h - Convert Mips Code to Machine Code -----------===// +//===- MipsMCCodeEmitter.h - Convert Mips Code to Machine Code --*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -10,29 +10,25 @@ // This file defines the MipsMCCodeEmitter class. // //===----------------------------------------------------------------------===// -// #ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCCODEEMITTER_H #define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCCODEEMITTER_H #include "llvm/MC/MCCodeEmitter.h" -#include "llvm/Support/DataTypes.h" - -using namespace llvm; +#include <cstdint> namespace llvm { + class MCContext; class MCExpr; +class MCFixup; class MCInst; class MCInstrInfo; -class MCFixup; class MCOperand; class MCSubtargetInfo; class raw_ostream; class MipsMCCodeEmitter : public MCCodeEmitter { - MipsMCCodeEmitter(const MipsMCCodeEmitter &) = delete; - void operator=(const MipsMCCodeEmitter &) = delete; const MCInstrInfo &MCII; MCContext &Ctx; bool IsLittleEndian; @@ -43,8 +39,9 @@ class MipsMCCodeEmitter : public MCCodeEmitter { public: MipsMCCodeEmitter(const MCInstrInfo &mcii, MCContext &Ctx_, bool IsLittle) : MCII(mcii), Ctx(Ctx_), IsLittleEndian(IsLittle) {} - - ~MipsMCCodeEmitter() override {} + MipsMCCodeEmitter(const MipsMCCodeEmitter &) = delete; + MipsMCCodeEmitter &operator=(const MipsMCCodeEmitter &) = delete; + ~MipsMCCodeEmitter() override = default; void EmitByte(unsigned char C, raw_ostream &OS) const; @@ -270,9 +267,11 @@ public: unsigned getRegisterListOpValue16(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; - private: + +private: void LowerCompactBranch(MCInst& Inst) const; -}; // class MipsMCCodeEmitter -} // namespace llvm. +}; + +} // end namespace llvm -#endif +#endif // LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCCODEEMITTER_H diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp index 082bb87fcb8a..be04480044d4 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp @@ -11,9 +11,15 @@ #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCContext.h" -#include "llvm/MC/MCObjectStreamer.h" #include "llvm/MC/MCSymbolELF.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/ELF.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include <cstdint> using namespace llvm; diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h b/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h index d1a4334ec640..495d525ccff4 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h +++ b/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h @@ -1,4 +1,4 @@ -//===-- MipsMCExpr.h - Mips specific MC expression classes ------*- C++ -*-===// +//===- MipsMCExpr.h - Mips specific MC expression classes -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -70,6 +70,7 @@ public: bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const override; void visitUsedExpr(MCStreamer &Streamer) const override; + MCFragment *findAssociatedFragment() const override { return getSubExpr()->findAssociatedFragment(); } @@ -86,6 +87,7 @@ public: return isGpOff(Kind); } }; + } // end namespace llvm -#endif +#endif // LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCEXPR_H diff --git a/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp b/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp index aef9bd3a8e2a..9266f0e216d1 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp @@ -20,7 +20,11 @@ #include "Mips.h" #include "MipsELFStreamer.h" #include "MipsMCNaCl.h" +#include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCELFStreamer.h" +#include "llvm/MC/MCInst.h" +#include "llvm/Support/ErrorHandling.h" +#include <cassert> using namespace llvm; @@ -38,14 +42,14 @@ class MipsNaClELFStreamer : public MipsELFStreamer { public: MipsNaClELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_pwrite_stream &OS, MCCodeEmitter *Emitter) - : MipsELFStreamer(Context, TAB, OS, Emitter), PendingCall(false) {} + : MipsELFStreamer(Context, TAB, OS, Emitter) {} - ~MipsNaClELFStreamer() override {} + ~MipsNaClELFStreamer() override = default; private: // Whether we started the sandboxing sequence for calls. Calls are bundled // with branch delays and aligned to the bundle end. - bool PendingCall; + bool PendingCall = false; bool isIndirectJump(const MCInst &MI) { if (MI.getOpcode() == Mips::JALR) { @@ -135,8 +139,8 @@ private: public: /// This function is the one used to emit instruction data into the ELF /// streamer. We override it to mask dangerous instructions. - void EmitInstruction(const MCInst &Inst, - const MCSubtargetInfo &STI) override { + void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, + bool) override { // Sandbox indirect jumps. if (isIndirectJump(Inst)) { if (PendingCall) @@ -265,4 +269,4 @@ MCELFStreamer *createMipsNaClELFStreamer(MCContext &Context, MCAsmBackend &TAB, return S; } -} +} // end namespace llvm diff --git a/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp b/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp index 24b602810d6e..74d5e4cc9841 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp @@ -1,4 +1,4 @@ -//===-- MipsOptionRecord.cpp - Abstraction for storing information --------===// +//===- MipsOptionRecord.cpp - Abstraction for storing information ---------===// // // The LLVM Compiler Infrastructure // @@ -7,10 +7,16 @@ // //===----------------------------------------------------------------------===// -#include "MipsOptionRecord.h" +#include "MipsABIInfo.h" #include "MipsELFStreamer.h" +#include "MipsOptionRecord.h" #include "MipsTargetStreamer.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSectionELF.h" +#include "llvm/Support/ELF.h" +#include <cassert> using namespace llvm; diff --git a/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp index 7f79eb400f59..2d4083b27ed1 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "MCTargetDesc/MipsABIInfo.h" #include "MipsTargetStreamer.h" #include "InstPrinter/MipsInstPrinter.h" #include "MipsELFStreamer.h" @@ -685,6 +686,17 @@ MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S, // issues as well. unsigned EFlags = MCA.getELFHeaderEFlags(); + // FIXME: Fix a dependency issue by instantiating the ABI object to some + // default based off the triple. The triple doesn't describe the target + // fully, but any external user of the API that uses the MCTargetStreamer + // would otherwise crash on assertion failure. + + ABI = MipsABIInfo( + STI.getTargetTriple().getArch() == Triple::ArchType::mipsel || + STI.getTargetTriple().getArch() == Triple::ArchType::mips + ? MipsABIInfo::O32() + : MipsABIInfo::N64()); + // Architecture if (Features[Mips::FeatureMips64r6]) EFlags |= ELF::EF_MIPS_ARCH_64R6; @@ -721,23 +733,18 @@ MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S, if (Features[Mips::FeatureNaN2008]) EFlags |= ELF::EF_MIPS_NAN2008; - // -mabicalls and -mplt are not implemented but we should act as if they were - // given. - EFlags |= ELF::EF_MIPS_CPIC; - MCA.setELFHeaderEFlags(EFlags); } void MipsTargetELFStreamer::emitLabel(MCSymbol *S) { auto *Symbol = cast<MCSymbolELF>(S); - if (!isMicroMipsEnabled()) - return; getStreamer().getAssembler().registerSymbol(*Symbol); uint8_t Type = Symbol->getType(); if (Type != ELF::STT_FUNC) return; - Symbol->setOther(ELF::STO_MIPS_MICROMIPS); + if (isMicroMipsEnabled()) + Symbol->setOther(ELF::STO_MIPS_MICROMIPS); } void MipsTargetELFStreamer::finish() { @@ -795,10 +802,13 @@ void MipsTargetELFStreamer::finish() { } else if (Features[Mips::FeatureMips64r2] || Features[Mips::FeatureMips64]) EFlags |= ELF::EF_MIPS_32BITMODE; - // If we've set the cpic eflag and we're n64, go ahead and set the pic - // one as well. - if (EFlags & ELF::EF_MIPS_CPIC && getABI().IsN64()) - EFlags |= ELF::EF_MIPS_PIC; + // -mplt is not implemented but we should act as if it was + // given. + if (!Features[Mips::FeatureNoABICalls]) + EFlags |= ELF::EF_MIPS_CPIC; + + if (Pic) + EFlags |= ELF::EF_MIPS_PIC | ELF::EF_MIPS_CPIC; MCA.setELFHeaderEFlags(EFlags); @@ -904,10 +914,10 @@ void MipsTargetELFStreamer::emitDirectiveEnd(StringRef Name) { const MCExpr *Size = MCBinaryExpr::createSub( MCSymbolRefExpr::create(CurPCSym, MCSymbolRefExpr::VK_None, Context), ExprRef, Context); - int64_t AbsSize; - if (!Size->evaluateAsAbsolute(AbsSize, MCA)) - llvm_unreachable("Function size must be evaluatable as absolute"); - Size = MCConstantExpr::create(AbsSize, Context); + + // The ELFObjectWriter can determine the absolute size as it has access to + // the layout information of the assembly file, so a size expression rather + // than an absolute value is ok here. static_cast<MCSymbolELF *>(Sym)->setSize(Size); } diff --git a/lib/Target/Mips/MicroMips64r6InstrInfo.td b/lib/Target/Mips/MicroMips64r6InstrInfo.td index 05aad515da46..6b7f39e9dd79 100644 --- a/lib/Target/Mips/MicroMips64r6InstrInfo.td +++ b/lib/Target/Mips/MicroMips64r6InstrInfo.td @@ -475,29 +475,11 @@ defm : MaterializeImms<i64, ZERO_64, DADDIU_MM64R6, LUi64, ORi64>; // //===----------------------------------------------------------------------===// -def : MipsPat<(MipsLo tglobaladdr:$in), - (DADDIU_MM64R6 ZERO_64, tglobaladdr:$in)>, ISA_MICROMIPS64R6; -def : MipsPat<(MipsLo tblockaddress:$in), - (DADDIU_MM64R6 ZERO_64, tblockaddress:$in)>, ISA_MICROMIPS64R6; -def : MipsPat<(MipsLo tjumptable:$in), - (DADDIU_MM64R6 ZERO_64, tjumptable:$in)>, ISA_MICROMIPS64R6; -def : MipsPat<(MipsLo tconstpool:$in), - (DADDIU_MM64R6 ZERO_64, tconstpool:$in)>, ISA_MICROMIPS64R6; -def : MipsPat<(MipsLo tglobaltlsaddr:$in), - (DADDIU_MM64R6 ZERO_64, tglobaltlsaddr:$in)>, ISA_MICROMIPS64R6; -def : MipsPat<(MipsLo texternalsym:$in), - (DADDIU_MM64R6 ZERO_64, texternalsym:$in)>, ISA_MICROMIPS64R6; - -def : MipsPat<(add GPR64:$hi, (MipsLo tglobaladdr:$lo)), - (DADDIU_MM64R6 GPR64:$hi, tglobaladdr:$lo)>, ISA_MICROMIPS64R6; -def : MipsPat<(add GPR64:$hi, (MipsLo tblockaddress:$lo)), - (DADDIU_MM64R6 GPR64:$hi, tblockaddress:$lo)>, ISA_MICROMIPS64R6; -def : MipsPat<(add GPR64:$hi, (MipsLo tjumptable:$lo)), - (DADDIU_MM64R6 GPR64:$hi, tjumptable:$lo)>, ISA_MICROMIPS64R6; -def : MipsPat<(add GPR64:$hi, (MipsLo tconstpool:$lo)), - (DADDIU_MM64R6 GPR64:$hi, tconstpool:$lo)>, ISA_MICROMIPS64R6; -def : MipsPat<(add GPR64:$hi, (MipsLo tglobaltlsaddr:$lo)), - (DADDIU_MM64R6 GPR64:$hi, tglobaltlsaddr:$lo)>, ISA_MICROMIPS64R6; +defm : MipsHiLoRelocs<LUi64, DADDIU_MM64R6, ZERO_64, GPR64Opnd>, SYM_32, + ISA_MICROMIPS64R6; + +defm : MipsHighestHigherHiLoRelocs<LUi64, DADDIU_MM64R6>, SYM_64, + ISA_MICROMIPS64R6; def : MipsPat<(addc GPR64:$lhs, GPR64:$rhs), (DADDU_MM64R6 GPR64:$lhs, GPR64:$rhs)>, ISA_MICROMIPS64R6; diff --git a/lib/Target/Mips/MicroMipsInstrInfo.td b/lib/Target/Mips/MicroMipsInstrInfo.td index c0de9e7390a4..ee554bc7f69a 100644 --- a/lib/Target/Mips/MicroMipsInstrInfo.td +++ b/lib/Target/Mips/MicroMipsInstrInfo.td @@ -1136,12 +1136,6 @@ let Predicates = [InMicroMips] in { def : MipsInstAlias< "sgtu $rs, $rt", (SLTu_MM GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; - def : MipsInstAlias<"slt $rs, $rt, $imm", - (SLTi_MM GPR32Opnd:$rs, GPR32Opnd:$rt, - simm32_relaxed:$imm), 0>; - def : MipsInstAlias<"sltu $rs, $rt, $imm", - (SLTiu_MM GPR32Opnd:$rs, GPR32Opnd:$rt, - simm32_relaxed:$imm), 0>; def : MipsInstAlias<"sll $rd, $rt, $rs", (SLLV_MM GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; def : MipsInstAlias<"sra $rd, $rt, $rs", @@ -1163,18 +1157,21 @@ let Predicates = [InMicroMips] in { def : MipsInstAlias<"rotr $rt, $imm", (ROTR_MM GPR32Opnd:$rt, GPR32Opnd:$rt, uimm5:$imm), 0>; def : MipsInstAlias<"syscall", (SYSCALL_MM 0), 1>; - def : MipsInstAlias<"and $rs, $rt, $imm", - (ANDi_MM GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>; - def : MipsInstAlias<"and $rs, $imm", - (ANDi_MM GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm), 0>; - def : MipsInstAlias<"or $rs, $rt, $imm", - (ORi_MM GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>; - def : MipsInstAlias<"or $rs, $imm", - (ORi_MM GPR32Opnd:$rs, GPR32Opnd:$rs, uimm16:$imm), 0>; - def : MipsInstAlias<"xor $rs, $rt, $imm", - (XORi_MM GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>; - def : MipsInstAlias<"xor $rs, $imm", - (XORi_MM GPR32Opnd:$rs, GPR32Opnd:$rs, uimm16:$imm), 0>; + + defm : OneOrTwoOperandMacroImmediateAlias<"add", ADDi_MM>; + + defm : OneOrTwoOperandMacroImmediateAlias<"addu", ADDiu_MM>; + + defm : OneOrTwoOperandMacroImmediateAlias<"and", ANDi_MM>; + + defm : OneOrTwoOperandMacroImmediateAlias<"or", ORi_MM>; + + defm : OneOrTwoOperandMacroImmediateAlias<"xor", XORi_MM>; + + defm : OneOrTwoOperandMacroImmediateAlias<"slt", SLTi_MM>; + + defm : OneOrTwoOperandMacroImmediateAlias<"sltu", SLTiu_MM>; + def : MipsInstAlias<"not $rt, $rs", (NOR_MM GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>; def : MipsInstAlias<"not $rt", diff --git a/lib/Target/Mips/Mips.td b/lib/Target/Mips/Mips.td index 670272d47e95..9615bc38bfce 100644 --- a/lib/Target/Mips/Mips.td +++ b/lib/Target/Mips/Mips.td @@ -156,6 +156,8 @@ def FeatureMips64r6 : SubtargetFeature<"mips64r6", "MipsArchVersion", "Mips64r6 ISA Support [experimental]", [FeatureMips32r6, FeatureMips64r5, FeatureNaN2008]>; +def FeatureSym32 : SubtargetFeature<"sym32", "HasSym32", "true", + "Symbols are 32 bit on Mips64">; def FeatureMips16 : SubtargetFeature<"mips16", "InMips16Mode", "true", "Mips16 mode">; diff --git a/lib/Target/Mips/Mips16HardFloat.cpp b/lib/Target/Mips/Mips16HardFloat.cpp index 191006d6463c..a71b161b24cc 100644 --- a/lib/Target/Mips/Mips16HardFloat.cpp +++ b/lib/Target/Mips/Mips16HardFloat.cpp @@ -405,7 +405,7 @@ static bool fixupFPReturnAndCall(Function &F, Module *M, "__mips16_ret_dc" }; const char *Name = Helper[RV]; - AttributeSet A; + AttributeList A; Value *Params[] = {RVal}; Modified = true; // @@ -414,13 +414,13 @@ static bool fixupFPReturnAndCall(Function &F, Module *M, // during call setup, the proper call lowering to the helper // functions will take place. // - A = A.addAttribute(C, AttributeSet::FunctionIndex, + A = A.addAttribute(C, AttributeList::FunctionIndex, "__Mips16RetHelper"); - A = A.addAttribute(C, AttributeSet::FunctionIndex, + A = A.addAttribute(C, AttributeList::FunctionIndex, Attribute::ReadNone); - A = A.addAttribute(C, AttributeSet::FunctionIndex, + A = A.addAttribute(C, AttributeList::FunctionIndex, Attribute::NoInline); - Value *F = (M->getOrInsertFunction(Name, A, MyVoid, T, nullptr)); + Value *F = (M->getOrInsertFunction(Name, A, MyVoid, T)); CallInst::Create(F, Params, "", &I); } else if (const CallInst *CI = dyn_cast<CallInst>(&I)) { FunctionType *FT = CI->getFunctionType(); @@ -490,15 +490,15 @@ static void createFPFnStub(Function *F, Module *M, FPParamVariant PV, // remove the use-soft-float attribute // static void removeUseSoftFloat(Function &F) { - AttributeSet A; + AttributeList A; DEBUG(errs() << "removing -use-soft-float\n"); - A = A.addAttribute(F.getContext(), AttributeSet::FunctionIndex, + A = A.addAttribute(F.getContext(), AttributeList::FunctionIndex, "use-soft-float", "false"); - F.removeAttributes(AttributeSet::FunctionIndex, A); + F.removeAttributes(AttributeList::FunctionIndex, A); if (F.hasFnAttribute("use-soft-float")) { DEBUG(errs() << "still has -use-soft-float\n"); } - F.addAttributes(AttributeSet::FunctionIndex, A); + F.addAttributes(AttributeList::FunctionIndex, A); } diff --git a/lib/Target/Mips/Mips16InstrInfo.td b/lib/Target/Mips/Mips16InstrInfo.td index 021fb8678686..52bf690a8083 100644 --- a/lib/Target/Mips/Mips16InstrInfo.td +++ b/lib/Target/Mips/Mips16InstrInfo.td @@ -766,6 +766,7 @@ def JrRa16: FRR16_JALRC_RA_only_ins<0, 0, "jr", IIM16Alu> { let hasDelaySlot = 1; let isTerminator=1; let isBarrier=1; + let isReturn=1; } def JrcRa16: FRR16_JALRC_RA_only_ins<1, 1, "jrc", IIM16Alu> { @@ -773,6 +774,7 @@ def JrcRa16: FRR16_JALRC_RA_only_ins<1, 1, "jrc", IIM16Alu> { let isIndirectBranch = 1; let isTerminator=1; let isBarrier=1; + let isReturn=1; } def JrcRx16: FRR16_JALRC_ins<1, 1, 0, "jrc", IIM16Alu> { diff --git a/lib/Target/Mips/Mips32r6InstrInfo.td b/lib/Target/Mips/Mips32r6InstrInfo.td index 1b4d73b79895..3272319ad50f 100644 --- a/lib/Target/Mips/Mips32r6InstrInfo.td +++ b/lib/Target/Mips/Mips32r6InstrInfo.td @@ -917,6 +917,12 @@ 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<"div $rs, $rt", (DIV GPR32Opnd:$rs, GPR32Opnd:$rs, + GPR32Opnd:$rt)>, ISA_MIPS32R6; +def : MipsInstAlias<"divu $rs, $rt", (DIVU GPR32Opnd:$rs, GPR32Opnd:$rs, + GPR32Opnd:$rt)>, ISA_MIPS32R6; + //===----------------------------------------------------------------------===// // // Patterns and Pseudo Instructions diff --git a/lib/Target/Mips/Mips64InstrInfo.td b/lib/Target/Mips/Mips64InstrInfo.td index 521e22fb7992..99025fe1341d 100644 --- a/lib/Target/Mips/Mips64InstrInfo.td +++ b/lib/Target/Mips/Mips64InstrInfo.td @@ -326,6 +326,14 @@ let AdditionalPredicates = [NotInMicroMips] in { EXT_FM<5>, ISA_MIPS64R2; } +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; +} + let isCodeGenOnly = 1, rs = 0, shamt = 0 in { def DSLL64_32 : FR<0x00, 0x3c, (outs GPR64:$rd), (ins GPR32:$rt), "dsll\t$rd, $rt, 32", [], II_DSLL>; @@ -356,11 +364,11 @@ class Count1s<string opstr, RegisterOperand RO>: let TwoOperandAliasConstraint = "$rd = $rs"; } -class ExtsCins<string opstr, InstrItinClass itin, - SDPatternOperator Op = null_frag>: - InstSE<(outs GPR64Opnd:$rt), (ins GPR64Opnd:$rs, uimm5:$pos, uimm5:$lenm1), - !strconcat(opstr, " $rt, $rs, $pos, $lenm1"), - [(set GPR64Opnd:$rt, (Op GPR64Opnd:$rs, imm:$pos, imm:$lenm1))], +class ExtsCins<string opstr, InstrItinClass itin, RegisterOperand RO, + PatFrag PosImm, SDPatternOperator Op = null_frag>: + InstSE<(outs RO:$rt), (ins RO:$rs, uimm5:$pos, uimm5:$lenm1), + !strconcat(opstr, "\t$rt, $rs, $pos, $lenm1"), + [(set RO:$rt, (Op RO:$rs, PosImm:$pos, imm:$lenm1))], itin, FrmR, opstr> { let TwoOperandAliasConstraint = "$rt = $rs"; } @@ -424,13 +432,28 @@ def DMUL : ArithLogicR<"dmul", GPR64Opnd, 1, II_DMUL, mul>, let Defs = [HI0, LO0, P0, P1, P2]; } -// Extract a signed bit field /+32 -def EXTS : ExtsCins<"exts", II_EXT>, EXTS_FM<0x3a>, ASE_CNMIPS; -def EXTS32: ExtsCins<"exts32", II_EXT>, EXTS_FM<0x3b>, ASE_CNMIPS; - -// Clear and insert a bit field /+32 -def CINS : ExtsCins<"cins", II_INS>, EXTS_FM<0x32>, ASE_CNMIPS; -def CINS32: ExtsCins<"cins32", II_INS>, EXTS_FM<0x33>, ASE_CNMIPS; +let AdditionalPredicates = [NotInMicroMips] in { + // Extract a signed bit field /+32 + def EXTS : ExtsCins<"exts", II_EXT, GPR64Opnd, immZExt5>, EXTS_FM<0x3a>, + ASE_MIPS64_CNMIPS; + def EXTS32: ExtsCins<"exts32", II_EXT, GPR64Opnd, immZExt5Plus32>, + EXTS_FM<0x3b>, ASE_MIPS64_CNMIPS; + + // Clear and insert a bit field /+32 + def CINS : ExtsCins<"cins", II_INS, GPR64Opnd, immZExt5, MipsCIns>, + EXTS_FM<0x32>, ASE_MIPS64_CNMIPS; + def CINS32: ExtsCins<"cins32", II_INS, GPR64Opnd, immZExt5Plus32, MipsCIns>, + EXTS_FM<0x33>, ASE_MIPS64_CNMIPS; + let isCodeGenOnly = 1 in { + def CINS_i32 : ExtsCins<"cins", II_INS, GPR32Opnd, immZExt5, MipsCIns>, + EXTS_FM<0x32>, ASE_MIPS64_CNMIPS; + def CINS64_32 :InstSE<(outs GPR64Opnd:$rt), + (ins GPR32Opnd:$rs, uimm5:$pos, uimm5:$lenm1), + "cins\t$rt, $rs, $pos, $lenm1", [], II_INS, FrmR, + "cins">, + EXTS_FM<0x32>, ASE_MIPS64_CNMIPS; + } +} // Move to multiplier/product register def MTM0 : MoveToLOHI<"mtm0", GPR64Opnd, [MPL0, P0, P1, P2]>, MTMR_FM<0x08>, @@ -513,41 +536,87 @@ def : MipsPat<(i64 (extloadi16 addr:$src)), (LH64 addr:$src)>; def : MipsPat<(i64 (extloadi32 addr:$src)), (LW64 addr:$src)>; // hi/lo relocs -def : MipsPat<(MipsHi tglobaladdr:$in), (LUi64 tglobaladdr:$in)>; -def : MipsPat<(MipsHi tblockaddress:$in), (LUi64 tblockaddress:$in)>; -def : MipsPat<(MipsHi tjumptable:$in), (LUi64 tjumptable:$in)>; -def : MipsPat<(MipsHi tconstpool:$in), (LUi64 tconstpool:$in)>; -def : MipsPat<(MipsHi tglobaltlsaddr:$in), (LUi64 tglobaltlsaddr:$in)>; -def : MipsPat<(MipsHi texternalsym:$in), (LUi64 texternalsym:$in)>; +let AdditionalPredicates = [NotInMicroMips] in +defm : MipsHiLoRelocs<LUi64, DADDiu, ZERO_64, GPR64Opnd>, SYM_32; + +def : MipsPat<(MipsGotHi tglobaladdr:$in), (LUi64 tglobaladdr:$in)>; +def : MipsPat<(MipsGotHi texternalsym:$in), (LUi64 texternalsym:$in)>; + +multiclass MipsHighestHigherHiLoRelocs<Instruction Lui, Instruction Daddiu> { + def : MipsPat<(MipsJmpLink (i64 texternalsym:$dst)), + (JAL texternalsym:$dst)>; + def : MipsPat<(MipsHighest (i64 tglobaladdr:$in)), + (Lui tglobaladdr:$in)>; + def : MipsPat<(MipsHighest (i64 tblockaddress:$in)), + (Lui tblockaddress:$in)>; + def : MipsPat<(MipsHighest (i64 tjumptable:$in)), + (Lui tjumptable:$in)>; + def : MipsPat<(MipsHighest (i64 tconstpool:$in)), + (Lui tconstpool:$in)>; + def : MipsPat<(MipsHighest (i64 tglobaltlsaddr:$in)), + (Lui tglobaltlsaddr:$in)>; + def : MipsPat<(MipsHighest (i64 texternalsym:$in)), + (Lui texternalsym:$in)>; + + def : MipsPat<(MipsHigher (i64 tglobaladdr:$in)), + (Daddiu ZERO_64, tglobaladdr:$in)>; + def : MipsPat<(MipsHigher (i64 tblockaddress:$in)), + (Daddiu ZERO_64, tblockaddress:$in)>; + def : MipsPat<(MipsHigher (i64 tjumptable:$in)), + (Daddiu ZERO_64, tjumptable:$in)>; + def : MipsPat<(MipsHigher (i64 tconstpool:$in)), + (Daddiu ZERO_64, tconstpool:$in)>; + def : MipsPat<(MipsHigher (i64 tglobaltlsaddr:$in)), + (Daddiu ZERO_64, tglobaltlsaddr:$in)>; + def : MipsPat<(MipsHigher (i64 texternalsym:$in)), + (Daddiu ZERO_64, texternalsym:$in)>; + + def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tglobaladdr:$lo))), + (Daddiu GPR64:$hi, tglobaladdr:$lo)>; + def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tblockaddress:$lo))), + (Daddiu GPR64:$hi, tblockaddress:$lo)>; + def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tjumptable:$lo))), + (Daddiu GPR64:$hi, tjumptable:$lo)>; + def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tconstpool:$lo))), + (Daddiu GPR64:$hi, tconstpool:$lo)>; + def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tglobaltlsaddr:$lo))), + (Daddiu GPR64:$hi, tglobaltlsaddr:$lo)>; + + def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tglobaladdr:$lo))), + (Daddiu GPR64:$hi, tglobaladdr:$lo)>; + def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tblockaddress:$lo))), + (Daddiu GPR64:$hi, tblockaddress:$lo)>; + def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tjumptable:$lo))), + (Daddiu GPR64:$hi, tjumptable:$lo)>; + def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tconstpool:$lo))), + (Daddiu GPR64:$hi, tconstpool:$lo)>; + def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tglobaltlsaddr:$lo))), + (Daddiu GPR64:$hi, tglobaltlsaddr:$lo)>; + + def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tglobaladdr:$lo))), + (Daddiu GPR64:$hi, tglobaladdr:$lo)>; + def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tblockaddress:$lo))), + (Daddiu GPR64:$hi, tblockaddress:$lo)>; + def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tjumptable:$lo))), + (Daddiu GPR64:$hi, tjumptable:$lo)>; + def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tconstpool:$lo))), + (Daddiu GPR64:$hi, tconstpool:$lo)>; + def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tglobaltlsaddr:$lo))), + (Daddiu GPR64:$hi, tglobaltlsaddr:$lo)>; + +} + +// highest/higher/hi/lo relocs +let AdditionalPredicates = [NotInMicroMips] in +defm : MipsHighestHigherHiLoRelocs<LUi64, DADDiu>, SYM_64; + +def : WrapperPat<tglobaladdr, DADDiu, GPR64>; +def : WrapperPat<tconstpool, DADDiu, GPR64>; +def : WrapperPat<texternalsym, DADDiu, GPR64>; +def : WrapperPat<tblockaddress, DADDiu, GPR64>; +def : WrapperPat<tjumptable, DADDiu, GPR64>; +def : WrapperPat<tglobaltlsaddr, DADDiu, GPR64>; -let AdditionalPredicates = [NotInMicroMips] in { - def : MipsPat<(MipsLo tglobaladdr:$in), (DADDiu ZERO_64, tglobaladdr:$in)>; - def : MipsPat<(MipsLo tblockaddress:$in), - (DADDiu ZERO_64, tblockaddress:$in)>; - def : MipsPat<(MipsLo tjumptable:$in), (DADDiu ZERO_64, tjumptable:$in)>; - def : MipsPat<(MipsLo tconstpool:$in), (DADDiu ZERO_64, tconstpool:$in)>; - def : MipsPat<(MipsLo tglobaltlsaddr:$in), - (DADDiu ZERO_64, tglobaltlsaddr:$in)>; - def : MipsPat<(MipsLo texternalsym:$in), (DADDiu ZERO_64, texternalsym:$in)>; - - def : MipsPat<(add GPR64:$hi, (MipsLo tglobaladdr:$lo)), - (DADDiu GPR64:$hi, tglobaladdr:$lo)>; - def : MipsPat<(add GPR64:$hi, (MipsLo tblockaddress:$lo)), - (DADDiu GPR64:$hi, tblockaddress:$lo)>; - def : MipsPat<(add GPR64:$hi, (MipsLo tjumptable:$lo)), - (DADDiu GPR64:$hi, tjumptable:$lo)>; - def : MipsPat<(add GPR64:$hi, (MipsLo tconstpool:$lo)), - (DADDiu GPR64:$hi, tconstpool:$lo)>; - def : MipsPat<(add GPR64:$hi, (MipsLo tglobaltlsaddr:$lo)), - (DADDiu GPR64:$hi, tglobaltlsaddr:$lo)>; - - def : WrapperPat<tglobaladdr, DADDiu, GPR64>; - def : WrapperPat<tconstpool, DADDiu, GPR64>; - def : WrapperPat<texternalsym, DADDiu, GPR64>; - def : WrapperPat<tblockaddress, DADDiu, GPR64>; - def : WrapperPat<tjumptable, DADDiu, GPR64>; - def : WrapperPat<tglobaltlsaddr, DADDiu, GPR64>; -} defm : BrcondPats<GPR64, BEQ64, BEQ, BNE64, SLT64, SLTu64, SLTi64, SLTiu64, ZERO_64>; @@ -600,6 +669,14 @@ def : MipsPat<(i64 (anyext GPR32:$src)), def : MipsPat<(i64 (zext GPR32:$src)), (DSRL (DSLL64_32 GPR32:$src), 32)>; def : MipsPat<(i64 (sext GPR32:$src)), (SLL64_32 GPR32:$src)>; +let AdditionalPredicates = [NotInMicroMips] in { + def : MipsPat<(i64 (zext GPR32:$src)), (DEXT64_32 GPR32:$src, 0, 32)>, + ISA_MIPS64R2; + def : MipsPat<(i64 (zext (i32 (shl GPR32:$rt, immZExt5:$imm)))), + (CINS64_32 GPR32:$rt, imm:$imm, (immZExt5To31 imm:$imm))>, + ASE_MIPS64_CNMIPS; +} + // Sign extend in register def : MipsPat<(i64 (sext_inreg GPR64:$src, i32)), (SLL64_64 GPR64:$src)>; @@ -661,6 +738,15 @@ let AdditionalPredicates = [NotInMicroMips] in { def : MipsInstAlias<"daddu $rs, $imm", (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm), 0>, ISA_MIPS3; + + defm : OneOrTwoOperandMacroImmediateAlias<"and", ANDi64, GPR64Opnd, imm64>, + GPR_64; + + defm : OneOrTwoOperandMacroImmediateAlias<"or", ORi64, GPR64Opnd, imm64>, + GPR_64; + + defm : OneOrTwoOperandMacroImmediateAlias<"xor", XORi64, GPR64Opnd, imm64>, + GPR_64; } def : MipsInstAlias<"dsll $rd, $rt, $rs", (DSLLV GPR64Opnd:$rd, GPR64Opnd:$rt, GPR32Opnd:$rs), 0>, @@ -741,21 +827,21 @@ def : MipsInstAlias<"bbit1 $rs, $p, $offset", def : MipsInstAlias<"exts $rt, $rs, $pos, $lenm1", (EXTS32 GPR64Opnd:$rt, GPR64Opnd:$rs, uimm5_plus32_normalize:$pos, uimm5:$lenm1), 0>, - ASE_CNMIPS; + ASE_MIPS64_CNMIPS; def : MipsInstAlias<"exts $rt, $pos, $lenm1", (EXTS32 GPR64Opnd:$rt, GPR64Opnd:$rt, uimm5_plus32_normalize:$pos, uimm5:$lenm1), 0>, - ASE_CNMIPS; + ASE_MIPS64_CNMIPS; // cins with $pos 32-63 in converted to cins32 with $pos 0-31 def : MipsInstAlias<"cins $rt, $rs, $pos, $lenm1", (CINS32 GPR64Opnd:$rt, GPR64Opnd:$rs, uimm5_plus32_normalize:$pos, uimm5:$lenm1), 0>, - ASE_CNMIPS; + ASE_MIPS64_CNMIPS; def : MipsInstAlias<"cins $rt, $pos, $lenm1", (CINS32 GPR64Opnd:$rt, GPR64Opnd:$rt, uimm5_plus32_normalize:$pos, uimm5:$lenm1), 0>, - ASE_CNMIPS; + ASE_MIPS64_CNMIPS; //===----------------------------------------------------------------------===// // Assembler Pseudo Instructions @@ -770,3 +856,81 @@ def LoadAddrReg64 : MipsAsmPseudoInst<(outs GPR64Opnd:$rt), (ins mem:$addr), "dla\t$rt, $addr">; def LoadAddrImm64 : MipsAsmPseudoInst<(outs GPR64Opnd:$rt), (ins imm64:$imm64), "dla\t$rt, $imm64">; + +def DMULImmMacro : MipsAsmPseudoInst<(outs), (ins GPR64Opnd:$rs, GPR64Opnd:$rt, + simm32_relaxed:$imm), + "dmul\t$rs, $rt, $imm">, + ISA_MIPS3_NOT_32R6_64R6; +def DMULOMacro : MipsAsmPseudoInst<(outs), (ins GPR64Opnd:$rs, GPR64Opnd:$rt, + GPR64Opnd:$rd), + "dmulo\t$rs, $rt, $rd">, + ISA_MIPS3_NOT_32R6_64R6; +def DMULOUMacro : MipsAsmPseudoInst<(outs), (ins GPR64Opnd:$rs, GPR64Opnd:$rt, + GPR64Opnd:$rd), + "dmulou\t$rs, $rt, $rd">, + ISA_MIPS3_NOT_32R6_64R6; + +def DMULMacro : MipsAsmPseudoInst<(outs), (ins GPR64Opnd:$rs, GPR64Opnd:$rt, + GPR64Opnd:$rd), + "dmul\t$rs, $rt, $rd"> { + let InsnPredicates = [HasMips3, NotMips64r6, NotCnMips]; +} + +let AdditionalPredicates = [NotInMicroMips] in { + def DSDivMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), + (ins GPR64Opnd:$rs, GPR64Opnd:$rt), + "ddiv\t$rd, $rs, $rt">, + ISA_MIPS3_NOT_32R6_64R6; + def DSDivIMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), + (ins GPR64Opnd:$rs, imm64:$imm), + "ddiv\t$rd, $rs, $imm">, + ISA_MIPS3_NOT_32R6_64R6; + def DUDivMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), + (ins GPR64Opnd:$rs, GPR64Opnd:$rt), + "ddivu\t$rd, $rs, $rt">, + ISA_MIPS3_NOT_32R6_64R6; + def DUDivIMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), + (ins GPR64Opnd:$rs, imm64:$imm), + "ddivu\t$rd, $rs, $imm">, + ISA_MIPS3_NOT_32R6_64R6; + + // GAS expands 'div' and 'ddiv' differently when the destination + // register is $zero and the instruction is in the two operand + // form. 'ddiv' gets expanded, while 'div' is not expanded. + + def : MipsInstAlias<"ddiv $rs, $rt", (DSDivMacro GPR64Opnd:$rs, + GPR64Opnd:$rs, + GPR64Opnd:$rt), 0>, + ISA_MIPS3_NOT_32R6_64R6; + def : MipsInstAlias<"ddiv $rd, $imm", (DSDivIMacro GPR64Opnd:$rd, + GPR64Opnd:$rd, + imm64:$imm), 0>, + ISA_MIPS3_NOT_32R6_64R6; + + // GAS expands 'divu' and 'ddivu' differently when the destination + // register is $zero and the instruction is in the two operand + // form. 'ddivu' gets expanded, while 'divu' is not expanded. + + def : MipsInstAlias<"ddivu $rt, $rs", (DUDivMacro GPR64Opnd:$rt, + GPR64Opnd:$rt, + GPR64Opnd:$rs), 0>, + ISA_MIPS3_NOT_32R6_64R6; + def : MipsInstAlias<"ddivu $rd, $imm", (DUDivIMacro GPR64Opnd:$rd, + GPR64Opnd:$rd, + imm64:$imm), 0>, + ISA_MIPS3_NOT_32R6_64R6; +} + +def NORImm64 : NORIMM_DESC_BASE<GPR64Opnd, imm64>, GPR_64; +def : MipsInstAlias<"nor\t$rs, $imm", (NORImm64 GPR64Opnd:$rs, GPR64Opnd:$rs, + imm64:$imm)>, GPR_64; +def SLTImm64 : MipsAsmPseudoInst<(outs GPR64Opnd:$rs), + (ins GPR64Opnd:$rt, imm64:$imm), + "slt\t$rs, $rt, $imm">, GPR_64; +def : MipsInstAlias<"slt\t$rs, $imm", (SLTImm64 GPR64Opnd:$rs, GPR64Opnd:$rs, + imm64:$imm)>, GPR_64; +def SLTUImm64 : MipsAsmPseudoInst<(outs GPR64Opnd:$rs), + (ins GPR64Opnd:$rt, imm64:$imm), + "sltu\t$rs, $rt, $imm">, GPR_64; +def : MipsInstAlias<"sltu\t$rs, $imm", (SLTUImm64 GPR64Opnd:$rs, GPR64Opnd:$rs, + imm64:$imm)>, GPR_64; diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp index 04d6529a073d..2a9d96205eb9 100644 --- a/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/MipsAsmPrinter.cpp @@ -39,6 +39,7 @@ #include "llvm/MC/MCELFStreamer.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstBuilder.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSymbolELF.h" @@ -79,6 +80,9 @@ bool MipsAsmPrinter::runOnMachineFunction(MachineFunction &MF) { NaClAlignIndirectJumpTargets(MF); AsmPrinter::runOnMachineFunction(MF); + + EmitXRayTable(); + return true; } @@ -132,6 +136,7 @@ void MipsAsmPrinter::emitPseudoIndirectBranch(MCStreamer &OutStreamer, void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { MipsTargetStreamer &TS = getTargetStreamer(); + unsigned Opc = MI->getOpcode(); TS.forbidModuleDirective(); if (MI->isDebugValue()) { @@ -143,20 +148,20 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { } // If we just ended a constant pool, mark it as such. - if (InConstantPool && MI->getOpcode() != Mips::CONSTPOOL_ENTRY) { + if (InConstantPool && Opc != Mips::CONSTPOOL_ENTRY) { OutStreamer->EmitDataRegion(MCDR_DataRegionEnd); InConstantPool = false; } - if (MI->getOpcode() == Mips::CONSTPOOL_ENTRY) { + if (Opc == Mips::CONSTPOOL_ENTRY) { // CONSTPOOL_ENTRY - This instruction represents a floating - //constant pool in the function. The first operand is the ID# + // constant pool in the function. The first operand is the ID# // for this instruction, the second is the index into the // MachineConstantPool that this is, the third is the size in // bytes of this constant pool entry. // The required alignment is specified on the basic block holding this MI. // unsigned LabelId = (unsigned)MI->getOperand(0).getImm(); - unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex(); + unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex(); // If this is the first entry of the pool, mark it. if (!InConstantPool) { @@ -174,6 +179,17 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { return; } + switch (Opc) { + case Mips::PATCHABLE_FUNCTION_ENTER: + LowerPATCHABLE_FUNCTION_ENTER(*MI); + return; + case Mips::PATCHABLE_FUNCTION_EXIT: + LowerPATCHABLE_FUNCTION_EXIT(*MI); + return; + case Mips::PATCHABLE_TAIL_CALL: + LowerPATCHABLE_TAIL_CALL(*MI); + return; + } MachineBasicBlock::const_instr_iterator I = MI->getIterator(); MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); @@ -574,6 +590,8 @@ void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, case MipsII::MO_GOT: O << "%got("; break; case MipsII::MO_ABS_HI: O << "%hi("; break; case MipsII::MO_ABS_LO: O << "%lo("; break; + case MipsII::MO_HIGHER: O << "%higher("; break; + case MipsII::MO_HIGHEST: O << "%highest(("; break; case MipsII::MO_TLSGD: O << "%tlsgd("; break; case MipsII::MO_GOTTPREL: O << "%gottprel("; break; case MipsII::MO_TPREL_HI: O << "%tprel_hi("; break; @@ -698,7 +716,7 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { // Ideally it should test for properties of the ABI and not the ABI // itself. // For the moment, I'm only correcting enough to make MIPS-IV work. - if (!isPositionIndependent() && !ABI.IsN64()) + if (!isPositionIndependent() && STI.hasSym32()) TS.emitDirectiveOptionPic0(); } @@ -1032,6 +1050,149 @@ void MipsAsmPrinter::EmitEndOfAsmFile(Module &M) { OutStreamer->SwitchSection(OutContext.getObjectFileInfo()->getTextSection()); } +void MipsAsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind) { + const uint8_t NoopsInSledCount = Subtarget->isGP64bit() ? 15 : 11; + // For mips32 we want to emit the following pattern: + // + // .Lxray_sled_N: + // ALIGN + // B .tmpN + // 11 NOP instructions (44 bytes) + // ADDIU T9, T9, 52 + // .tmpN + // + // We need the 44 bytes (11 instructions) because at runtime, we'd + // be patching over the full 48 bytes (12 instructions) with the following + // pattern: + // + // ADDIU SP, SP, -8 + // NOP + // SW RA, 4(SP) + // SW T9, 0(SP) + // LUI T9, %hi(__xray_FunctionEntry/Exit) + // ORI T9, T9, %lo(__xray_FunctionEntry/Exit) + // LUI T0, %hi(function_id) + // JALR T9 + // ORI T0, T0, %lo(function_id) + // LW T9, 0(SP) + // LW RA, 4(SP) + // ADDIU SP, SP, 8 + // + // We add 52 bytes to t9 because we want to adjust the function pointer to + // the actual start of function i.e. the address just after the noop sled. + // We do this because gp displacement relocation is emitted at the start of + // of the function i.e after the nop sled and to correctly calculate the + // global offset table address, t9 must hold the address of the instruction + // containing the gp displacement relocation. + // FIXME: Is this correct for the static relocation model? + // + // For mips64 we want to emit the following pattern: + // + // .Lxray_sled_N: + // ALIGN + // B .tmpN + // 15 NOP instructions (60 bytes) + // .tmpN + // + // We need the 60 bytes (15 instructions) because at runtime, we'd + // be patching over the full 64 bytes (16 instructions) with the following + // pattern: + // + // DADDIU SP, SP, -16 + // NOP + // SD RA, 8(SP) + // SD T9, 0(SP) + // LUI T9, %highest(__xray_FunctionEntry/Exit) + // ORI T9, T9, %higher(__xray_FunctionEntry/Exit) + // DSLL T9, T9, 16 + // ORI T9, T9, %hi(__xray_FunctionEntry/Exit) + // DSLL T9, T9, 16 + // ORI T9, T9, %lo(__xray_FunctionEntry/Exit) + // LUI T0, %hi(function_id) + // JALR T9 + // ADDIU T0, T0, %lo(function_id) + // LD T9, 0(SP) + // LD RA, 8(SP) + // DADDIU SP, SP, 16 + // + OutStreamer->EmitCodeAlignment(4); + auto CurSled = OutContext.createTempSymbol("xray_sled_", true); + OutStreamer->EmitLabel(CurSled); + auto Target = OutContext.createTempSymbol(); + + // Emit "B .tmpN" instruction, which jumps over the nop sled to the actual + // start of function + const MCExpr *TargetExpr = MCSymbolRefExpr::create( + Target, MCSymbolRefExpr::VariantKind::VK_None, OutContext); + EmitToStreamer(*OutStreamer, MCInstBuilder(Mips::BEQ) + .addReg(Mips::ZERO) + .addReg(Mips::ZERO) + .addExpr(TargetExpr)); + + for (int8_t I = 0; I < NoopsInSledCount; I++) + EmitToStreamer(*OutStreamer, MCInstBuilder(Mips::SLL) + .addReg(Mips::ZERO) + .addReg(Mips::ZERO) + .addImm(0)); + + OutStreamer->EmitLabel(Target); + + if (!Subtarget->isGP64bit()) { + EmitToStreamer(*OutStreamer, + MCInstBuilder(Mips::ADDiu) + .addReg(Mips::T9) + .addReg(Mips::T9) + .addImm(0x34)); + } + + recordSled(CurSled, MI, Kind); +} + +void MipsAsmPrinter::EmitXRayTable() { + if (Sleds.empty()) + return; + if (Subtarget->isTargetELF()) { + auto PrevSection = OutStreamer->getCurrentSectionOnly(); + auto Fn = MF->getFunction(); + MCSection *Section; + + if (Fn->hasComdat()) + Section = OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | ELF::SHF_GROUP, 0, + Fn->getComdat()->getName()); + else + Section = + OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC, 0, CurrentFnSym->getName()); + + OutStreamer->SwitchSection(Section); + for (const auto &Sled : Sleds) { + OutStreamer->EmitSymbolValue(Sled.Sled, Subtarget->isGP64bit() ? 8 : 4); + OutStreamer->EmitSymbolValue(CurrentFnSym, Subtarget->isGP64bit() ? 8 : 4); + auto Kind = static_cast<uint8_t>(Sled.Kind); + OutStreamer->EmitBytes( + StringRef(reinterpret_cast<const char *>(&Kind), 1)); + OutStreamer->EmitBytes( + StringRef(reinterpret_cast<const char *>(&Sled.AlwaysInstrument), 1)); + OutStreamer->EmitZeros(Subtarget->isGP64bit() ? 14 : 6); + } + OutStreamer->SwitchSection(PrevSection); + } + Sleds.clear(); +} + +void MipsAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI) { + EmitSled(MI, SledKind::FUNCTION_ENTER); +} + +void MipsAsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI) { + EmitSled(MI, SledKind::FUNCTION_EXIT); +} + +void MipsAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI) { + EmitSled(MI, SledKind::TAIL_CALL); +} + void MipsAsmPrinter::PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS) { // TODO: implement @@ -1039,7 +1200,7 @@ void MipsAsmPrinter::PrintDebugValueComment(const MachineInstr *MI, // Emit .dtprelword or .dtpreldword directive // and value for debug thread local expression. -void MipsAsmPrinter::EmitDebugValue(const MCExpr *Value, +void MipsAsmPrinter::EmitDebugThreadLocal(const MCExpr *Value, unsigned Size) const { switch (Size) { case 4: diff --git a/lib/Target/Mips/MipsAsmPrinter.h b/lib/Target/Mips/MipsAsmPrinter.h index c5cf5241c236..4699e1b0bd3b 100644 --- a/lib/Target/Mips/MipsAsmPrinter.h +++ b/lib/Target/Mips/MipsAsmPrinter.h @@ -35,7 +35,21 @@ class LLVM_LIBRARY_VISIBILITY MipsAsmPrinter : public AsmPrinter { void EmitInstrWithMacroNoAT(const MachineInstr *MI); + //===------------------------------------------------------------------===// + // XRay implementation + //===------------------------------------------------------------------===// +public: + // XRay-specific lowering for Mips. + void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI); + void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI); + void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI); + // Helper function that emits the XRay sleds we've collected for a particular + // function. + void EmitXRayTable(); + private: + void EmitSled(const MachineInstr &MI, SledKind Kind); + // tblgen'erated function. bool emitPseudoExpansionLowering(MCStreamer &OutStreamer, const MachineInstr *MI); @@ -140,7 +154,7 @@ public: void EmitStartOfAsmFile(Module &M) override; void EmitEndOfAsmFile(Module &M) override; void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS); - void EmitDebugValue(const MCExpr *Value, unsigned Size) const override; + void EmitDebugThreadLocal(const MCExpr *Value, unsigned Size) const override; }; } diff --git a/lib/Target/Mips/MipsConstantIslandPass.cpp b/lib/Target/Mips/MipsConstantIslandPass.cpp index 08b8ed31ccbb..026f66a1c0e1 100644 --- a/lib/Target/Mips/MipsConstantIslandPass.cpp +++ b/lib/Target/Mips/MipsConstantIslandPass.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// // -// // This pass is used to make Pc relative loads of constants. // For now, only Mips16 will use this. // @@ -19,30 +18,43 @@ // This can be particularly helpful in static relocation mode for embedded // non-linux targets. // -// +//===----------------------------------------------------------------------===// #include "Mips.h" -#include "MCTargetDesc/MipsBaseInfo.h" #include "Mips16InstrInfo.h" #include "MipsMachineFunction.h" -#include "MipsTargetMachine.h" +#include "MipsSubtarget.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DebugLoc.h" #include "llvm/IR/Function.h" -#include "llvm/IR/InstIterator.h" +#include "llvm/IR/Type.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetRegisterInfo.h" #include <algorithm> +#include <cassert> +#include <cstdint> +#include <iterator> +#include <new> +#include <vector> using namespace llvm; @@ -58,7 +70,6 @@ static cl::opt<bool> AlignConstantIslands("mips-align-constant-islands", cl::Hidden, cl::init(true), cl::desc("Align constant islands in code")); - // Rather than do make check tests with huge amounts of code, we force // the test to use this amount. // @@ -178,7 +189,6 @@ static unsigned int branchMaxOffsets(unsigned int Opcode) { namespace { - typedef MachineBasicBlock::iterator Iter; typedef MachineBasicBlock::reverse_iterator ReverseIter; @@ -195,7 +205,6 @@ namespace { /// tracks a list of users. class MipsConstantIslands : public MachineFunctionPass { - /// BasicBlockInfo - Information about the offset and size of a single /// basic block. struct BasicBlockInfo { @@ -208,14 +217,16 @@ namespace { /// /// Because worst case padding is used, the computed offset of an aligned /// block may not actually be aligned. - unsigned Offset; + unsigned Offset = 0; /// Size - Size of the basic block in bytes. If the block contains /// inline assembly, this is a worst case estimate. /// /// The size does not include any alignment padding whether from the /// beginning of the block, or from an aligned jump table at the end. - unsigned Size; + unsigned Size = 0; + + BasicBlockInfo() = default; // FIXME: ignore LogAlign for this patch // @@ -223,9 +234,6 @@ namespace { unsigned PO = Offset + Size; return PO; } - - BasicBlockInfo() : Offset(0), Size(0) {} - }; std::vector<BasicBlockInfo> BBInfo; @@ -257,13 +265,16 @@ namespace { MachineInstr *MI; MachineInstr *CPEMI; MachineBasicBlock *HighWaterMark; + private: unsigned MaxDisp; unsigned LongFormMaxDisp; // mips16 has 16/32 bit instructions // with different displacements unsigned LongFormOpcode; + public: bool NegOk; + CPUser(MachineInstr *mi, MachineInstr *cpemi, unsigned maxdisp, bool neg, unsigned longformmaxdisp, unsigned longformopcode) @@ -272,18 +283,22 @@ namespace { NegOk(neg){ HighWaterMark = CPEMI->getParent(); } + /// getMaxDisp - Returns the maximum displacement supported by MI. unsigned getMaxDisp() const { unsigned xMaxDisp = ConstantIslandsSmallOffset? ConstantIslandsSmallOffset: MaxDisp; return xMaxDisp; } + void setMaxDisp(unsigned val) { MaxDisp = val; } + unsigned getLongFormMaxDisp() const { return LongFormMaxDisp; } + unsigned getLongFormOpcode() const { return LongFormOpcode; } @@ -300,6 +315,7 @@ namespace { MachineInstr *CPEMI; unsigned CPI; unsigned RefCount; + CPEntry(MachineInstr *cpemi, unsigned cpi, unsigned rc = 0) : CPEMI(cpemi), CPI(cpi), RefCount(rc) {} }; @@ -309,7 +325,7 @@ namespace { /// existed upon entry to this pass), it keeps a vector of entries. /// Original elements are cloned as we go along; the clones are /// put in the vector of the original element, but have distinct CPIs. - std::vector<std::vector<CPEntry> > CPEntries; + std::vector<std::vector<CPEntry>> CPEntries; /// ImmBranch - One per immediate branch, keeping the machine instruction /// pointer, conditional or unconditional, the max displacement, @@ -320,6 +336,7 @@ namespace { unsigned MaxDisp : 31; bool isCond : 1; int UncondBr; + ImmBranch(MachineInstr *mi, unsigned maxdisp, bool cond, int ubr) : MI(mi), MaxDisp(maxdisp), isCond(cond), UncondBr(ubr) {} }; @@ -332,29 +349,27 @@ namespace { /// the branch fix up pass. bool HasFarJump; - const MipsSubtarget *STI; + const MipsSubtarget *STI = nullptr; const Mips16InstrInfo *TII; MipsFunctionInfo *MFI; - MachineFunction *MF; - MachineConstantPool *MCP; + MachineFunction *MF = nullptr; + MachineConstantPool *MCP = nullptr; unsigned PICLabelUId; - bool PrescannedForConstants; + bool PrescannedForConstants = false; void initPICLabelUId(unsigned UId) { PICLabelUId = UId; } - unsigned createPICLabelUId() { return PICLabelUId++; } public: static char ID; - MipsConstantIslands() - : MachineFunctionPass(ID), STI(nullptr), MF(nullptr), MCP(nullptr), - PrescannedForConstants(false) {} + + MipsConstantIslands() : MachineFunctionPass(ID) {} StringRef getPassName() const override { return "Mips Constant Islands"; } @@ -403,13 +418,11 @@ namespace { bool fixupUnconditionalBr(ImmBranch &Br); void prescanForConstants(); - - private: - }; char MipsConstantIslands::ID = 0; -} // end of anonymous namespace + +} // end anonymous namespace bool MipsConstantIslands::isOffsetInRange (unsigned UserOffset, unsigned TrialOffset, @@ -417,20 +430,17 @@ bool MipsConstantIslands::isOffsetInRange return isOffsetInRange(UserOffset, TrialOffset, U.getMaxDisp(), U.NegOk); } + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) /// print block size and offset information - debugging -void MipsConstantIslands::dumpBBs() { - DEBUG({ - for (unsigned J = 0, E = BBInfo.size(); J !=E; ++J) { - const BasicBlockInfo &BBI = BBInfo[J]; - dbgs() << format("%08x BB#%u\t", BBI.Offset, J) - << format(" size=%#x\n", BBInfo[J].Size); - } - }); -} -/// Returns a pass that converts branches to long branches. -FunctionPass *llvm::createMipsConstantIslandPass() { - return new MipsConstantIslands(); +LLVM_DUMP_METHOD void MipsConstantIslands::dumpBBs() { + for (unsigned J = 0, E = BBInfo.size(); J !=E; ++J) { + const BasicBlockInfo &BBI = BBInfo[J]; + dbgs() << format("%08x BB#%u\t", BBI.Offset, J) + << format(" size=%#x\n", BBInfo[J].Size); + } } +#endif bool MipsConstantIslands::runOnMachineFunction(MachineFunction &mf) { // The intention is for this to be a mips16 only pass for now @@ -527,7 +537,6 @@ MipsConstantIslands::doInitialPlacement(std::vector<MachineInstr*> &CPEMIs) { MachineBasicBlock *BB = MF->CreateMachineBasicBlock(); MF->push_back(BB); - // MachineConstantPool measures alignment in bytes. We measure in log2(bytes). unsigned MaxAlign = Log2_32(MCP->getConstantPoolAlignment()); @@ -647,7 +656,6 @@ initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) { for (MachineFunction::iterator I = MF->begin(), E = MF->end(); I != E; ++I) computeBlockSize(&*I); - // Compute block offsets. adjustBBOffsetsAfter(&MF->front()); @@ -737,7 +745,6 @@ initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) { if (Opc == Mips::CONSTPOOL_ENTRY) continue; - // Scan the instructions for constant pool operands. for (unsigned op = 0, e = MI.getNumOperands(); op != e; ++op) if (MI.getOperand(op).isCPI()) { @@ -784,12 +791,9 @@ initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) { // Instructions can only use one CP entry, don't bother scanning the // rest of the operands. break; - } - } } - } /// computeBlockSize - Compute the size and some alignment information for MBB. @@ -921,8 +925,6 @@ MipsConstantIslands::splitBlockBeforeInstr(MachineInstr &MI) { return NewBB; } - - /// isOffsetInRange - Checks whether UserOffset (the location of a constant pool /// reference) is within MaxDisp of TrialOffset (a proposed location of a /// constant pool entry). @@ -1337,7 +1339,6 @@ bool MipsConstantIslands::handleConstantPoolUser(unsigned CPUserIndex) { if (result==1) return false; else if (result==2) return true; - // Look for water where we can place this CPE. MachineBasicBlock *NewIsland = MF->CreateMachineBasicBlock(); MachineBasicBlock *NewMBB; @@ -1371,7 +1372,7 @@ bool MipsConstantIslands::handleConstantPoolUser(unsigned CPUserIndex) { // it. Check for this so it will be removed from the WaterList. // Also remove any entry from NewWaterList. MachineBasicBlock *WaterBB = &*--NewMBB->getIterator(); - IP = find(WaterList, WaterBB); + IP = llvm::find(WaterList, WaterBB); if (IP != WaterList.end()) NewWaterList.erase(WaterBB); @@ -1473,9 +1474,7 @@ bool MipsConstantIslands::removeUnusedCPEntries() { /// specific BB can fit in MI's displacement field. bool MipsConstantIslands::isBBInRange (MachineInstr *MI,MachineBasicBlock *DestBB, unsigned MaxDisp) { - -unsigned PCAdj = 4; - + unsigned PCAdj = 4; unsigned BrOffset = getOffsetOf(MI) + PCAdj; unsigned DestOffset = BBInfo[DestBB->getNumber()].Offset; @@ -1553,7 +1552,6 @@ MipsConstantIslands::fixupUnconditionalBr(ImmBranch &Br) { return true; } - /// fixupConditionalBr - Fix up a conditional branch whose destination is too /// far away to fit in its displacement field. It is converted to an inverse /// conditional branch + an unconditional branch to the destination. @@ -1614,7 +1612,6 @@ MipsConstantIslands::fixupConditionalBr(ImmBranch &Br) { } } - if (NeedSplit) { splitBlockBeforeInstr(*MI); // No need for the branch to the next block. We're adding an unconditional @@ -1654,7 +1651,6 @@ MipsConstantIslands::fixupConditionalBr(ImmBranch &Br) { return true; } - void MipsConstantIslands::prescanForConstants() { unsigned J = 0; (void)J; @@ -1667,11 +1663,11 @@ void MipsConstantIslands::prescanForConstants() { PrescannedForConstants = true; DEBUG(dbgs() << "constant island constant " << *I << "\n"); J = I->getNumOperands(); - DEBUG(dbgs() << "num operands " << J << "\n"); + DEBUG(dbgs() << "num operands " << J << "\n"); MachineOperand& Literal = I->getOperand(1); if (Literal.isImm()) { int64_t V = Literal.getImm(); - DEBUG(dbgs() << "literal " << V << "\n"); + DEBUG(dbgs() << "literal " << V << "\n"); Type *Int32Ty = Type::getInt32Ty(MF->getFunction()->getContext()); const Constant *C = ConstantInt::get(Int32Ty, V); @@ -1692,3 +1688,8 @@ void MipsConstantIslands::prescanForConstants() { } } } + +/// Returns a pass that converts branches to long branches. +FunctionPass *llvm::createMipsConstantIslandPass() { + return new MipsConstantIslands(); +} diff --git a/lib/Target/Mips/MipsDelaySlotFiller.cpp b/lib/Target/Mips/MipsDelaySlotFiller.cpp index c821084f68cf..ae58c26e145a 100644 --- a/lib/Target/Mips/MipsDelaySlotFiller.cpp +++ b/lib/Target/Mips/MipsDelaySlotFiller.cpp @@ -14,21 +14,39 @@ #include "MCTargetDesc/MipsMCNaCl.h" #include "Mips.h" #include "MipsInstrInfo.h" +#include "MipsSubtarget.h" #include "MipsTargetMachine.h" #include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/ValueTracking.h" +#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineBranchProbabilityInfo.h" +#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/MC/MCInstrDesc.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/CodeGen.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" +#include <algorithm> +#include <cassert> +#include <iterator> +#include <memory> +#include <utility> using namespace llvm; @@ -84,6 +102,7 @@ static cl::opt<CompactBranchPolicy> MipsCompactBranchPolicy( ); namespace { + typedef MachineBasicBlock::iterator Iter; typedef MachineBasicBlock::reverse_iterator ReverseIter; typedef SmallDenseMap<MachineBasicBlock*, MachineInstr*, 2> BB2BrMap; @@ -91,6 +110,7 @@ namespace { class RegDefsUses { public: RegDefsUses(const TargetRegisterInfo &TRI); + void init(const MachineInstr &MI); /// This function sets all caller-saved registers in Defs. @@ -120,18 +140,18 @@ namespace { /// Base class for inspecting loads and stores. class InspectMemInstr { public: - InspectMemInstr(bool ForbidMemInstr_) - : OrigSeenLoad(false), OrigSeenStore(false), SeenLoad(false), - SeenStore(false), ForbidMemInstr(ForbidMemInstr_) {} + InspectMemInstr(bool ForbidMemInstr_) : ForbidMemInstr(ForbidMemInstr_) {} + virtual ~InspectMemInstr() = default; /// Return true if MI cannot be moved to delay slot. bool hasHazard(const MachineInstr &MI); - virtual ~InspectMemInstr() {} - protected: /// Flags indicating whether loads or stores have been seen. - bool OrigSeenLoad, OrigSeenStore, SeenLoad, SeenStore; + bool OrigSeenLoad = false; + bool OrigSeenStore = false; + bool SeenLoad = false; + bool SeenStore = false; /// Memory instructions are not allowed to move to delay slot if this flag /// is true. @@ -145,6 +165,7 @@ namespace { class NoMemInstr : public InspectMemInstr { public: NoMemInstr() : InspectMemInstr(true) {} + private: bool hasHazard_(const MachineInstr &MI) override { return true; } }; @@ -153,6 +174,7 @@ namespace { class LoadFromStackOrConst : public InspectMemInstr { public: LoadFromStackOrConst() : InspectMemInstr(false) {} + private: bool hasHazard_(const MachineInstr &MI) override; }; @@ -183,7 +205,8 @@ namespace { /// Flags indicating whether loads or stores with no underlying objects have /// been seen. - bool SeenNoObjLoad, SeenNoObjStore; + bool SeenNoObjLoad = false; + bool SeenNoObjStore = false; }; class Filler : public MachineFunctionPass { @@ -271,8 +294,10 @@ namespace { static char ID; }; + char Filler::ID = 0; -} // end of anonymous namespace + +} // end anonymous namespace static bool hasUnoccupiedSlot(const MachineInstr *MI) { return MI->hasDelaySlot() && !MI->isBundledWithSucc(); @@ -458,8 +483,7 @@ bool LoadFromStackOrConst::hasHazard_(const MachineInstr &MI) { } MemDefsUses::MemDefsUses(const DataLayout &DL, const MachineFrameInfo *MFI_) - : InspectMemInstr(false), MFI(MFI_), DL(DL), SeenNoObjLoad(false), - SeenNoObjStore(false) {} + : InspectMemInstr(false), MFI(MFI_), DL(DL) {} bool MemDefsUses::hasHazard_(const MachineInstr &MI) { bool HasHazard = false; @@ -646,12 +670,6 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { return Changed; } -/// createMipsDelaySlotFillerPass - Returns a pass that fills in delay -/// slots in Mips MachineFunctions -FunctionPass *llvm::createMipsDelaySlotFillerPass(MipsTargetMachine &tm) { - return new Filler(tm); -} - template<typename IterTy> bool Filler::searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End, RegDefsUses &RegDU, InspectMemInstr& IM, Iter Slot, @@ -889,3 +907,9 @@ bool Filler::terminateSearch(const MachineInstr &Candidate) const { Candidate.isPosition() || Candidate.isInlineAsm() || Candidate.hasUnmodeledSideEffects()); } + +/// createMipsDelaySlotFillerPass - Returns a pass that fills in delay +/// slots in Mips MachineFunctions +FunctionPass *llvm::createMipsDelaySlotFillerPass(MipsTargetMachine &tm) { + return new Filler(tm); +} diff --git a/lib/Target/Mips/MipsFastISel.cpp b/lib/Target/Mips/MipsFastISel.cpp index a44192f57aa0..c060cf06099d 100644 --- a/lib/Target/Mips/MipsFastISel.cpp +++ b/lib/Target/Mips/MipsFastISel.cpp @@ -1,4 +1,4 @@ -//===-- MipsFastISel.cpp - Mips FastISel implementation --------------------===// +//===-- MipsFastISel.cpp - Mips FastISel implementation -------------------===// // // The LLVM Compiler Infrastructure // @@ -14,24 +14,62 @@ /// //===----------------------------------------------------------------------===// +#include "MCTargetDesc/MipsABIInfo.h" +#include "MCTargetDesc/MipsBaseInfo.h" #include "MipsCCState.h" #include "MipsInstrInfo.h" #include "MipsISelLowering.h" #include "MipsMachineFunction.h" -#include "MipsRegisterInfo.h" #include "MipsSubtarget.h" #include "MipsTargetMachine.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/FastISel.h" #include "llvm/CodeGen/FunctionLoweringInfo.h" +#include "llvm/CodeGen/ISDOpcodes.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/MachineValueType.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/IR/Attributes.h" +#include "llvm/IR/CallingConv.h" +#include "llvm/IR/Constant.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Function.h" #include "llvm/IR/GetElementPtrTypeIterator.h" -#include "llvm/IR/GlobalAlias.h" +#include "llvm/IR/GlobalValue.h" #include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Operator.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/User.h" +#include "llvm/IR/Value.h" +#include "llvm/MC/MCInstrDesc.h" +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetLowering.h" +#include <algorithm> +#include <cassert> +#include <cstdint> +#include <new> #define DEBUG_TYPE "mips-fastisel" @@ -47,35 +85,40 @@ class MipsFastISel final : public FastISel { typedef enum { RegBase, FrameIndexBase } BaseKind; private: - BaseKind Kind; + BaseKind Kind = RegBase; union { unsigned Reg; int FI; } Base; - int64_t Offset; + int64_t Offset = 0; - const GlobalValue *GV; + const GlobalValue *GV = nullptr; public: // Innocuous defaults for our address. - Address() : Kind(RegBase), Offset(0), GV(0) { Base.Reg = 0; } + Address() { Base.Reg = 0; } + void setKind(BaseKind K) { Kind = K; } BaseKind getKind() const { return Kind; } bool isRegBase() const { return Kind == RegBase; } bool isFIBase() const { return Kind == FrameIndexBase; } + void setReg(unsigned Reg) { assert(isRegBase() && "Invalid base register access!"); Base.Reg = Reg; } + unsigned getReg() const { assert(isRegBase() && "Invalid base register access!"); return Base.Reg; } + void setFI(unsigned FI) { assert(isFIBase() && "Invalid base frame index access!"); Base.FI = FI; } + unsigned getFI() const { assert(isFIBase() && "Invalid base frame index access!"); return Base.FI; @@ -165,14 +208,17 @@ private: MachineInstrBuilder emitInst(unsigned Opc) { return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)); } + MachineInstrBuilder emitInst(unsigned Opc, unsigned DstReg) { return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), DstReg); } + MachineInstrBuilder emitInstStore(unsigned Opc, unsigned SrcReg, unsigned MemReg, int64_t MemOffset) { return emitInst(Opc).addReg(SrcReg).addReg(MemReg).addImm(MemOffset); } + MachineInstrBuilder emitInstLoad(unsigned Opc, unsigned DstReg, unsigned MemReg, int64_t MemOffset) { return emitInst(Opc, DstReg).addReg(MemReg).addImm(MemOffset); @@ -198,6 +244,7 @@ private: bool processCallArgs(CallLoweringInfo &CLI, SmallVectorImpl<MVT> &ArgVTs, unsigned &NumBytes); bool finishCall(CallLoweringInfo &CLI, MVT RetVT, unsigned NumBytes); + const MipsABIInfo &getABI() const { return static_cast<const MipsTargetMachine &>(TM).getABI(); } @@ -220,7 +267,8 @@ public: #include "MipsGenFastISel.inc" }; -} // end anonymous namespace. + +} // end anonymous namespace static bool CC_Mips(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, @@ -414,7 +462,6 @@ unsigned MipsFastISel::fastMaterializeConstant(const Constant *C) { } bool MipsFastISel::computeAddress(const Value *Obj, Address &Addr) { - const User *U = nullptr; unsigned Opcode = Instruction::UserOp1; if (const Instruction *I = dyn_cast<Instruction>(Obj)) { @@ -432,10 +479,9 @@ bool MipsFastISel::computeAddress(const Value *Obj, Address &Addr) { switch (Opcode) { default: break; - case Instruction::BitCast: { + case Instruction::BitCast: // Look through bitcasts. return computeAddress(U->getOperand(0), Addr); - } case Instruction::GetElementPtr: { Address SavedAddr = Addr; int64_t TmpOffset = Addr.getOffset(); @@ -451,7 +497,7 @@ bool MipsFastISel::computeAddress(const Value *Obj, Address &Addr) { TmpOffset += SL->getElementOffset(Idx); } else { uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType()); - for (;;) { + while (true) { if (const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) { // Constant-offset addressing. TmpOffset += CI->getSExtValue() * S; @@ -613,14 +659,12 @@ bool MipsFastISel::emitCmp(unsigned ResultReg, const CmpInst *CI) { emitInst(Mips::SLTu, ResultReg).addReg(Mips::ZERO).addReg(TempReg); break; } - case CmpInst::ICMP_UGT: { + case CmpInst::ICMP_UGT: emitInst(Mips::SLTu, ResultReg).addReg(RightReg).addReg(LeftReg); break; - } - case CmpInst::ICMP_ULT: { + case CmpInst::ICMP_ULT: emitInst(Mips::SLTu, ResultReg).addReg(LeftReg).addReg(RightReg); break; - } case CmpInst::ICMP_UGE: { unsigned TempReg = createResultReg(&Mips::GPR32RegClass); emitInst(Mips::SLTu, TempReg).addReg(LeftReg).addReg(RightReg); @@ -633,14 +677,12 @@ bool MipsFastISel::emitCmp(unsigned ResultReg, const CmpInst *CI) { emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1); break; } - case CmpInst::ICMP_SGT: { + case CmpInst::ICMP_SGT: emitInst(Mips::SLT, ResultReg).addReg(RightReg).addReg(LeftReg); break; - } - case CmpInst::ICMP_SLT: { + case CmpInst::ICMP_SLT: emitInst(Mips::SLT, ResultReg).addReg(LeftReg).addReg(RightReg); break; - } case CmpInst::ICMP_SGE: { unsigned TempReg = createResultReg(&Mips::GPR32RegClass); emitInst(Mips::SLT, TempReg).addReg(LeftReg).addReg(RightReg); @@ -709,6 +751,7 @@ bool MipsFastISel::emitCmp(unsigned ResultReg, const CmpInst *CI) { } return true; } + bool MipsFastISel::emitLoad(MVT VT, unsigned &ResultReg, Address &Addr, unsigned Alignment) { // @@ -716,35 +759,30 @@ bool MipsFastISel::emitLoad(MVT VT, unsigned &ResultReg, Address &Addr, // unsigned Opc; switch (VT.SimpleTy) { - case MVT::i32: { + case MVT::i32: ResultReg = createResultReg(&Mips::GPR32RegClass); Opc = Mips::LW; break; - } - case MVT::i16: { + case MVT::i16: ResultReg = createResultReg(&Mips::GPR32RegClass); Opc = Mips::LHu; break; - } - case MVT::i8: { + case MVT::i8: ResultReg = createResultReg(&Mips::GPR32RegClass); Opc = Mips::LBu; break; - } - case MVT::f32: { + case MVT::f32: if (UnsupportedFPMode) return false; ResultReg = createResultReg(&Mips::FGR32RegClass); Opc = Mips::LWC1; break; - } - case MVT::f64: { + case MVT::f64: if (UnsupportedFPMode) return false; ResultReg = createResultReg(&Mips::AFGR64RegClass); Opc = Mips::LDC1; break; - } default: return false; } @@ -1730,6 +1768,7 @@ bool MipsFastISel::selectTrunc(const Instruction *I) { updateValueMap(I, SrcReg); return true; } + bool MipsFastISel::selectIntExt(const Instruction *I) { Type *DestTy = I->getType(); Value *Src = I->getOperand(0); @@ -1757,6 +1796,7 @@ bool MipsFastISel::selectIntExt(const Instruction *I) { updateValueMap(I, ResultReg); return true; } + bool MipsFastISel::emitIntSExt32r1(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg) { unsigned ShiftAmt; @@ -2074,8 +2114,10 @@ unsigned MipsFastISel::fastEmitInst_rr(unsigned MachineInstOpcode, } namespace llvm { + FastISel *Mips::createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo) { return new MipsFastISel(funcInfo, libInfo); } -} + +} // end namespace llvm diff --git a/lib/Target/Mips/MipsHazardSchedule.cpp b/lib/Target/Mips/MipsHazardSchedule.cpp index 31b86124bc8d..f6fcf6ec9385 100644 --- a/lib/Target/Mips/MipsHazardSchedule.cpp +++ b/lib/Target/Mips/MipsHazardSchedule.cpp @@ -36,7 +36,7 @@ /// /// A) A previous pass has created a compact branch directly. /// B) Transforming a delay slot branch into compact branch. This case can be -/// difficult to process as lookahead for hazards is insufficent, as +/// difficult to process as lookahead for hazards is insufficient, as /// backwards delay slot fillling can also produce hazards in previously /// processed instuctions. /// @@ -103,23 +103,24 @@ static Iter getNextMachineInstrInBB(Iter Position) { // Find the next real instruction from the current position, looking through // basic block boundaries. -static Iter getNextMachineInstr(Iter Position, MachineBasicBlock *Parent) { +static std::pair<Iter, bool> getNextMachineInstr(Iter Position, MachineBasicBlock * Parent) { if (Position == Parent->end()) { - MachineBasicBlock *Succ = Parent->getNextNode(); - if (Succ != nullptr && Parent->isSuccessor(Succ)) { - Position = Succ->begin(); - Parent = Succ; - } else { - llvm_unreachable( - "Should have identified the end of the function earlier!"); - } + do { + MachineBasicBlock *Succ = Parent->getNextNode(); + if (Succ != nullptr && Parent->isSuccessor(Succ)) { + Position = Succ->begin(); + Parent = Succ; + } else { + return std::make_pair(Position, true); + } + } while (Parent->empty()); } Iter Instr = getNextMachineInstrInBB(Position); if (Instr == Parent->end()) { return getNextMachineInstr(Instr, Parent); } - return Instr; + return std::make_pair(Instr, false); } bool MipsHazardSchedule::runOnMachineFunction(MachineFunction &MF) { @@ -145,7 +146,9 @@ bool MipsHazardSchedule::runOnMachineFunction(MachineFunction &MF) { bool LastInstInFunction = std::next(I) == FI->end() && std::next(FI) == MF.end(); if (!LastInstInFunction) { - Inst = getNextMachineInstr(std::next(I), &*FI); + std::pair<Iter, bool> Res = getNextMachineInstr(std::next(I), &*FI); + LastInstInFunction |= Res.second; + Inst = Res.first; } if (LastInstInFunction || !TII->SafeInForbiddenSlot(*Inst)) { diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 9c511bd77822..93c5f496ce97 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -112,8 +112,11 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { case MipsISD::FIRST_NUMBER: break; case MipsISD::JmpLink: return "MipsISD::JmpLink"; case MipsISD::TailCall: return "MipsISD::TailCall"; + case MipsISD::Highest: return "MipsISD::Highest"; + case MipsISD::Higher: return "MipsISD::Higher"; case MipsISD::Hi: return "MipsISD::Hi"; case MipsISD::Lo: return "MipsISD::Lo"; + case MipsISD::GotHi: return "MipsISD::GotHi"; case MipsISD::GPRel: return "MipsISD::GPRel"; case MipsISD::ThreadPointer: return "MipsISD::ThreadPointer"; case MipsISD::Ret: return "MipsISD::Ret"; @@ -144,6 +147,7 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { case MipsISD::Sync: return "MipsISD::Sync"; case MipsISD::Ext: return "MipsISD::Ext"; case MipsISD::Ins: return "MipsISD::Ins"; + case MipsISD::CIns: return "MipsISD::CIns"; case MipsISD::LWL: return "MipsISD::LWL"; case MipsISD::LWR: return "MipsISD::LWR"; case MipsISD::SWL: return "MipsISD::SWL"; @@ -425,6 +429,7 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, setTargetDAGCombine(ISD::OR); setTargetDAGCombine(ISD::ADD); setTargetDAGCombine(ISD::AssertZext); + setTargetDAGCombine(ISD::SHL); if (ABI.IsO32()) { // These libcalls are not available in 32-bit. @@ -699,41 +704,81 @@ static SDValue performCMovFPCombine(SDNode *N, SelectionDAG &DAG, static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const MipsSubtarget &Subtarget) { - // Pattern match EXT. - // $dst = and ((sra or srl) $src , pos), (2**size - 1) - // => ext $dst, $src, size, pos if (DCI.isBeforeLegalizeOps() || !Subtarget.hasExtractInsert()) return SDValue(); - SDValue ShiftRight = N->getOperand(0), Mask = N->getOperand(1); - unsigned ShiftRightOpc = ShiftRight.getOpcode(); - - // Op's first operand must be a shift right. - if (ShiftRightOpc != ISD::SRA && ShiftRightOpc != ISD::SRL) - return SDValue(); + SDValue FirstOperand = N->getOperand(0); + unsigned FirstOperandOpc = FirstOperand.getOpcode(); + SDValue Mask = N->getOperand(1); + EVT ValTy = N->getValueType(0); + SDLoc DL(N); - // The second operand of the shift must be an immediate. + uint64_t Pos = 0, SMPos, SMSize; ConstantSDNode *CN; - if (!(CN = dyn_cast<ConstantSDNode>(ShiftRight.getOperand(1)))) - return SDValue(); - - uint64_t Pos = CN->getZExtValue(); - uint64_t SMPos, SMSize; + SDValue NewOperand; + unsigned Opc; // Op's second operand must be a shifted mask. if (!(CN = dyn_cast<ConstantSDNode>(Mask)) || !isShiftedMask(CN->getZExtValue(), SMPos, SMSize)) return SDValue(); - // Return if the shifted mask does not start at bit 0 or the sum of its size - // and Pos exceeds the word's size. - EVT ValTy = N->getValueType(0); - if (SMPos != 0 || Pos + SMSize > ValTy.getSizeInBits()) - return SDValue(); + if (FirstOperandOpc == ISD::SRA || FirstOperandOpc == ISD::SRL) { + // Pattern match EXT. + // $dst = and ((sra or srl) $src , pos), (2**size - 1) + // => ext $dst, $src, pos, size + + // The second operand of the shift must be an immediate. + if (!(CN = dyn_cast<ConstantSDNode>(FirstOperand.getOperand(1)))) + return SDValue(); + + Pos = CN->getZExtValue(); + + // Return if the shifted mask does not start at bit 0 or the sum of its size + // and Pos exceeds the word's size. + if (SMPos != 0 || Pos + SMSize > ValTy.getSizeInBits()) + return SDValue(); + + Opc = MipsISD::Ext; + NewOperand = FirstOperand.getOperand(0); + } else if (FirstOperandOpc == ISD::SHL && Subtarget.hasCnMips()) { + // Pattern match CINS. + // $dst = and (shl $src , pos), mask + // => cins $dst, $src, pos, size + // mask is a shifted mask with consecutive 1's, pos = shift amount, + // size = population count. + + // The second operand of the shift must be an immediate. + if (!(CN = dyn_cast<ConstantSDNode>(FirstOperand.getOperand(1)))) + return SDValue(); + + Pos = CN->getZExtValue(); + + if (SMPos != Pos || Pos >= ValTy.getSizeInBits() || SMSize >= 32 || + Pos + SMSize > ValTy.getSizeInBits()) + return SDValue(); + + NewOperand = FirstOperand.getOperand(0); + // SMSize is 'location' (position) in this case, not size. + SMSize--; + Opc = MipsISD::CIns; + } else { + // Pattern match EXT. + // $dst = and $src, (2**size - 1) , if size > 16 + // => ext $dst, $src, pos, size , pos = 0 - SDLoc DL(N); - return DAG.getNode(MipsISD::Ext, DL, ValTy, - ShiftRight.getOperand(0), + // If the mask is <= 0xffff, andi can be used instead. + if (CN->getZExtValue() <= 0xffff) + return SDValue(); + + // Return if the mask doesn't start at position 0. + if (SMPos) + return SDValue(); + + Opc = MipsISD::Ext; + NewOperand = FirstOperand; + } + return DAG.getNode(Opc, DL, ValTy, NewOperand, DAG.getConstant(Pos, DL, MVT::i32), DAG.getConstant(SMSize, DL, MVT::i32)); } @@ -852,6 +897,58 @@ static SDValue performAssertZextCombine(SDNode *N, SelectionDAG &DAG, return SDValue(); } + +static SDValue performSHLCombine(SDNode *N, SelectionDAG &DAG, + TargetLowering::DAGCombinerInfo &DCI, + const MipsSubtarget &Subtarget) { + // Pattern match CINS. + // $dst = shl (and $src , imm), pos + // => cins $dst, $src, pos, size + + if (DCI.isBeforeLegalizeOps() || !Subtarget.hasCnMips()) + return SDValue(); + + SDValue FirstOperand = N->getOperand(0); + unsigned FirstOperandOpc = FirstOperand.getOpcode(); + SDValue SecondOperand = N->getOperand(1); + EVT ValTy = N->getValueType(0); + SDLoc DL(N); + + uint64_t Pos = 0, SMPos, SMSize; + ConstantSDNode *CN; + SDValue NewOperand; + + // The second operand of the shift must be an immediate. + if (!(CN = dyn_cast<ConstantSDNode>(SecondOperand))) + return SDValue(); + + Pos = CN->getZExtValue(); + + if (Pos >= ValTy.getSizeInBits()) + return SDValue(); + + if (FirstOperandOpc != ISD::AND) + return SDValue(); + + // AND's second operand must be a shifted mask. + if (!(CN = dyn_cast<ConstantSDNode>(FirstOperand.getOperand(1))) || + !isShiftedMask(CN->getZExtValue(), SMPos, SMSize)) + return SDValue(); + + // Return if the shifted mask does not start at bit 0 or the sum of its size + // and Pos exceeds the word's size. + if (SMPos != 0 || SMSize > 32 || Pos + SMSize > ValTy.getSizeInBits()) + return SDValue(); + + NewOperand = FirstOperand.getOperand(0); + // SMSize is 'location' (position) in this case, not size. + SMSize--; + + return DAG.getNode(MipsISD::CIns, DL, ValTy, NewOperand, + DAG.getConstant(Pos, DL, MVT::i32), + DAG.getConstant(SMSize, DL, MVT::i32)); +} + SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { SelectionDAG &DAG = DCI.DAG; @@ -875,6 +972,8 @@ SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) return performADDCombine(N, DAG, DCI, Subtarget); case ISD::AssertZext: return performAssertZextCombine(N, DAG, DCI, Subtarget); + case ISD::SHL: + return performSHLCombine(N, DAG, DCI, Subtarget); } return SDValue(); @@ -1733,7 +1832,7 @@ SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op, GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op); const GlobalValue *GV = N->getGlobal(); - if (!isPositionIndependent() && !ABI.IsN64()) { + if (!isPositionIndependent()) { const MipsTargetObjectFile *TLOF = static_cast<const MipsTargetObjectFile *>( getTargetMachine().getObjFileLowering()); @@ -1742,8 +1841,10 @@ SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op, // %gp_rel relocation return getAddrGPRel(N, SDLoc(N), Ty, DAG); - // %hi/%lo relocation - return getAddrNonPIC(N, SDLoc(N), Ty, DAG); + // %hi/%lo relocation + return Subtarget.hasSym32() ? getAddrNonPIC(N, SDLoc(N), Ty, DAG) + // %highest/%higher/%hi/%lo relocation + : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG); } // Every other architecture would use shouldAssumeDSOLocal in here, but @@ -1777,8 +1878,9 @@ SDValue MipsTargetLowering::lowerBlockAddress(SDValue Op, BlockAddressSDNode *N = cast<BlockAddressSDNode>(Op); EVT Ty = Op.getValueType(); - if (!isPositionIndependent() && !ABI.IsN64()) - return getAddrNonPIC(N, SDLoc(N), Ty, DAG); + if (!isPositionIndependent()) + return Subtarget.hasSym32() ? getAddrNonPIC(N, SDLoc(N), Ty, DAG) + : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG); return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64()); } @@ -1820,8 +1922,9 @@ lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const Args.push_back(Entry); TargetLowering::CallLoweringInfo CLI(DAG); - CLI.setDebugLoc(DL).setChain(DAG.getEntryNode()) - .setCallee(CallingConv::C, PtrTy, TlsGetAddr, std::move(Args)); + CLI.setDebugLoc(DL) + .setChain(DAG.getEntryNode()) + .setLibCallee(CallingConv::C, PtrTy, TlsGetAddr, std::move(Args)); std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI); SDValue Ret = CallResult.first; @@ -1870,8 +1973,9 @@ lowerJumpTable(SDValue Op, SelectionDAG &DAG) const JumpTableSDNode *N = cast<JumpTableSDNode>(Op); EVT Ty = Op.getValueType(); - if (!isPositionIndependent() && !ABI.IsN64()) - return getAddrNonPIC(N, SDLoc(N), Ty, DAG); + if (!isPositionIndependent()) + return Subtarget.hasSym32() ? getAddrNonPIC(N, SDLoc(N), Ty, DAG) + : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG); return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64()); } @@ -1882,7 +1986,7 @@ lowerConstantPool(SDValue Op, SelectionDAG &DAG) const ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op); EVT Ty = Op.getValueType(); - if (!isPositionIndependent() && !ABI.IsN64()) { + if (!isPositionIndependent()) { const MipsTargetObjectFile *TLOF = static_cast<const MipsTargetObjectFile *>( getTargetMachine().getObjFileLowering()); @@ -1892,10 +1996,11 @@ lowerConstantPool(SDValue Op, SelectionDAG &DAG) const // %gp_rel relocation return getAddrGPRel(N, SDLoc(N), Ty, DAG); - return getAddrNonPIC(N, SDLoc(N), Ty, DAG); + return Subtarget.hasSym32() ? getAddrNonPIC(N, SDLoc(N), Ty, DAG) + : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG); } - return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64()); + return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64()); } SDValue MipsTargetLowering::lowerVASTART(SDValue Op, SelectionDAG &DAG) const { @@ -2796,14 +2901,13 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol // node so that legalize doesn't hack it. - bool IsPICCall = (ABI.IsN64() || IsPIC); // true if calls are translated to - // jalr $25 + SDValue CalleeLo; EVT Ty = Callee.getValueType(); bool GlobalOrExternal = false, IsCallReloc = false; if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) { - if (IsPICCall) { + if (IsPIC) { const GlobalValue *Val = G->getGlobal(); InternalLinkage = Val->hasInternalLinkage(); @@ -2828,7 +2932,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) { const char *Sym = S->getSymbol(); - if (!ABI.IsN64() && !IsPIC) // !N64 && static + if (!IsPIC) // static Callee = DAG.getTargetExternalSymbol( Sym, getPointerTy(DAG.getDataLayout()), MipsII::MO_NO_FLAG); else if (LargeGOT) { @@ -2836,7 +2940,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, MipsII::MO_CALL_LO16, Chain, FuncInfo->callPtrInfo(Sym)); IsCallReloc = true; - } else { // N64 || PIC + } else { // PIC Callee = getAddrGlobal(S, DL, Ty, DAG, MipsII::MO_GOT_CALL, Chain, FuncInfo->callPtrInfo(Sym)); IsCallReloc = true; @@ -2848,7 +2952,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVector<SDValue, 8> Ops(1, Chain); SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); - getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal, InternalLinkage, + getOpndList(Ops, RegsToPass, IsPIC, GlobalOrExternal, InternalLinkage, IsCallReloc, CLI, Callee, Chain); if (IsTailCall) { @@ -3683,7 +3787,9 @@ bool MipsTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const { } unsigned MipsTargetLowering::getJumpTableEncoding() const { - if (ABI.IsN64()) + + // FIXME: For space reasons this should be: EK_GPRel32BlockAddress. + if (ABI.IsN64() && isPositionIndependent()) return MachineJumpTableInfo::EK_GPRel64BlockAddress; return TargetLowering::getJumpTableEncoding(); diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index cddf0903ca6a..2dcafd51061a 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -37,14 +37,23 @@ namespace llvm { // Tail call TailCall, - // Get the Higher 16 bits from a 32-bit immediate + // Get the Highest (63-48) 16 bits from a 64-bit immediate + Highest, + + // Get the Higher (47-32) 16 bits from a 64-bit immediate + Higher, + + // Get the High 16 bits from a 32/64-bit immediate // No relation with Mips Hi register Hi, - // Get the Lower 16 bits from a 32-bit immediate + // Get the Lower 16 bits from a 32/64-bit immediate // No relation with Mips Lo register Lo, + // Get the High 16 bits from a 32 bit immediate for accessing the GOT. + GotHi, + // Handle gp_rel (small data/bss sections) relocation. GPRel, @@ -107,6 +116,7 @@ namespace llvm { Ext, Ins, + CIns, // EXTR.W instrinsic nodes. EXTP, @@ -297,7 +307,7 @@ namespace llvm { } bool isJumpTableRelative() const override { - return getTargetMachine().isPositionIndependent() || ABI.IsN64(); + return getTargetMachine().isPositionIndependent(); } protected: @@ -344,8 +354,8 @@ namespace llvm { SelectionDAG &DAG, unsigned HiFlag, unsigned LoFlag, SDValue Chain, const MachinePointerInfo &PtrInfo) const { - SDValue Hi = - DAG.getNode(MipsISD::Hi, DL, Ty, getTargetNode(N, Ty, DAG, HiFlag)); + SDValue Hi = DAG.getNode(MipsISD::GotHi, DL, Ty, + getTargetNode(N, Ty, DAG, HiFlag)); Hi = DAG.getNode(ISD::ADD, DL, Ty, Hi, getGlobalReg(DAG, Ty)); SDValue Wrapper = DAG.getNode(MipsISD::Wrapper, DL, Ty, Hi, getTargetNode(N, Ty, DAG, LoFlag)); @@ -356,6 +366,8 @@ namespace llvm { // computing a symbol's address in non-PIC mode: // // (add %hi(sym), %lo(sym)) + // + // This method covers O32, N32 and N64 in sym32 mode. template <class NodeTy> SDValue getAddrNonPIC(NodeTy *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG) const { @@ -364,7 +376,37 @@ namespace llvm { return DAG.getNode(ISD::ADD, DL, Ty, DAG.getNode(MipsISD::Hi, DL, Ty, Hi), DAG.getNode(MipsISD::Lo, DL, Ty, Lo)); - } + } + + // This method creates the following nodes, which are necessary for + // computing a symbol's address in non-PIC mode for N64. + // + // (add (shl (add (shl (add %highest(sym), %higher(sim)), 16), %high(sym)), + // 16), %lo(%sym)) + // + // FIXME: This method is not efficent for (micro)MIPS64R6. + template <class NodeTy> + SDValue getAddrNonPICSym64(NodeTy *N, const SDLoc &DL, EVT Ty, + SelectionDAG &DAG) const { + SDValue Hi = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_HI); + SDValue Lo = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_LO); + + SDValue Highest = + DAG.getNode(MipsISD::Highest, DL, Ty, + getTargetNode(N, Ty, DAG, MipsII::MO_HIGHEST)); + SDValue Higher = getTargetNode(N, Ty, DAG, MipsII::MO_HIGHER); + SDValue HigherPart = + DAG.getNode(ISD::ADD, DL, Ty, Highest, + DAG.getNode(MipsISD::Higher, DL, Ty, Higher)); + SDValue Cst = DAG.getConstant(16, DL, MVT::i32); + SDValue Shift = DAG.getNode(ISD::SHL, DL, Ty, HigherPart, Cst); + SDValue Add = DAG.getNode(ISD::ADD, DL, Ty, Shift, + DAG.getNode(MipsISD::Hi, DL, Ty, Hi)); + SDValue Shift2 = DAG.getNode(ISD::SHL, DL, Ty, Add, Cst); + + return DAG.getNode(ISD::ADD, DL, Ty, Shift2, + DAG.getNode(MipsISD::Lo, DL, Ty, Lo)); + } // This method creates the following nodes, which are necessary for // computing a symbol's address using gp-relative addressing: diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp index 19af1914c819..df62c66b75a3 100644 --- a/lib/Target/Mips/MipsInstrInfo.cpp +++ b/lib/Target/Mips/MipsInstrInfo.cpp @@ -482,7 +482,7 @@ MipsInstrInfo::genInstrWithNewOpc(unsigned NewOpc, MIB->RemoveOperand(0); for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) { - MIB.addOperand(I->getOperand(J)); + MIB.add(I->getOperand(J)); } MIB.addImm(0); @@ -492,7 +492,7 @@ MipsInstrInfo::genInstrWithNewOpc(unsigned NewOpc, if (BranchWithZeroOperand && (unsigned)ZeroOperandPosition == J) continue; - MIB.addOperand(I->getOperand(J)); + MIB.add(I->getOperand(J)); } } @@ -501,3 +501,31 @@ MipsInstrInfo::genInstrWithNewOpc(unsigned NewOpc, MIB.setMemRefs(I->memoperands_begin(), I->memoperands_end()); return MIB; } + +bool MipsInstrInfo::findCommutedOpIndices(MachineInstr &MI, unsigned &SrcOpIdx1, + unsigned &SrcOpIdx2) const { + assert(!MI.isBundle() && + "TargetInstrInfo::findCommutedOpIndices() can't handle bundles"); + + const MCInstrDesc &MCID = MI.getDesc(); + if (!MCID.isCommutable()) + return false; + + switch (MI.getOpcode()) { + case Mips::DPADD_U_H: + case Mips::DPADD_U_W: + case Mips::DPADD_U_D: + case Mips::DPADD_S_H: + case Mips::DPADD_S_W: + case Mips::DPADD_S_D: { + // The first operand is both input and output, so it should not commute + if (!fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 2, 3)) + return false; + + if (!MI.getOperand(SrcOpIdx1).isReg() || !MI.getOperand(SrcOpIdx2).isReg()) + return false; + return true; + } + } + return TargetInstrInfo::findCommutedOpIndices(MI, SrcOpIdx1, SrcOpIdx2); +} diff --git a/lib/Target/Mips/MipsInstrInfo.h b/lib/Target/Mips/MipsInstrInfo.h index 347b9187d08c..45d700d8afd6 100644 --- a/lib/Target/Mips/MipsInstrInfo.h +++ b/lib/Target/Mips/MipsInstrInfo.h @@ -135,6 +135,9 @@ public: MachineInstrBuilder genInstrWithNewOpc(unsigned NewOpc, MachineBasicBlock::iterator I) const; + bool findCommutedOpIndices(MachineInstr &MI, unsigned &SrcOpIdx1, + unsigned &SrcOpIdx2) const override; + protected: bool isZeroImm(const MachineOperand &op) const; diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index 5bc48336121a..b90077d7807d 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -59,10 +59,20 @@ def MipsTailCall : SDNode<"MipsISD::TailCall", SDT_MipsJmpLink, // Hi and Lo nodes are used to handle global addresses. Used on // MipsISelLowering to lower stuff like GlobalAddress, ExternalSymbol // static model. (nothing to do with Mips Registers Hi and Lo) + +// Hi is the odd node out, on MIPS64 it can expand to either daddiu when +// using static relocations with 64 bit symbols, or lui when using 32 bit +// symbols. +def MipsHigher : SDNode<"MipsISD::Higher", SDTIntUnaryOp>; +def MipsHighest : SDNode<"MipsISD::Highest", SDTIntUnaryOp>; def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp>; def MipsLo : SDNode<"MipsISD::Lo", SDTIntUnaryOp>; + def MipsGPRel : SDNode<"MipsISD::GPRel", SDTIntUnaryOp>; +// Hi node for accessing the GOT. +def MipsGotHi : SDNode<"MipsISD::GotHi", SDTIntUnaryOp>; + // TlsGd node is used to handle General Dynamic TLS def MipsTlsGd : SDNode<"MipsISD::TlsGd", SDTIntUnaryOp>; @@ -128,6 +138,7 @@ def MipsSync : SDNode<"MipsISD::Sync", SDT_Sync, [SDNPHasChain,SDNPSideEffect]>; def MipsExt : SDNode<"MipsISD::Ext", SDT_Ext>; def MipsIns : SDNode<"MipsISD::Ins", SDT_Ins>; +def MipsCIns : SDNode<"MipsISD::CIns", SDT_Ext>; def MipsLWL : SDNode<"MipsISD::LWL", SDTMipsLoadLR, [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; @@ -205,6 +216,10 @@ def HasCnMips : Predicate<"Subtarget->hasCnMips()">, AssemblerPredicate<"FeatureCnMips">; def NotCnMips : Predicate<"!Subtarget->hasCnMips()">, AssemblerPredicate<"!FeatureCnMips">; +def IsSym32 : Predicate<"Subtarget->HasSym32()">, + AssemblerPredicate<"FeatureSym32">; +def IsSym64 : Predicate<"!Subtarget->HasSym32()">, + AssemblerPredicate<"!FeatureSym32">; def RelocNotPIC : Predicate<"!TM.isPositionIndependent()">; def RelocPIC : Predicate<"TM.isPositionIndependent()">; def NoNaNsFPMath : Predicate<"TM.Options.NoNaNsFPMath">; @@ -237,6 +252,14 @@ class PTR_32 { list<Predicate> PTRPredicates = [IsPTR32bit]; } class PTR_64 { list<Predicate> PTRPredicates = [IsPTR64bit]; } //===----------------------------------------------------------------------===// +// Mips Symbol size adjectives. +// They are mutally exculsive. +//===----------------------------------------------------------------------===// + +class SYM_32 { list<Predicate> SYMPredicates = [IsSym32]; } +class SYM_64 { list<Predicate> SYMPredicates = [IsSym64]; } + +//===----------------------------------------------------------------------===// // Mips ISA/ASE membership and instruction group membership adjectives. // They are mutually exclusive. //===----------------------------------------------------------------------===// @@ -519,7 +542,7 @@ def UImm32CoercedAsmOperandClass : UImmAnyAsmOperandClass<33, []> { def SImm32RelaxedAsmOperandClass : SImmAsmOperandClass<32, [UImm32CoercedAsmOperandClass]> { let Name = "SImm32_Relaxed"; - let PredicateMethod = "isAnyImm<32>"; + let PredicateMethod = "isAnyImm<33>"; let DiagnosticType = "SImm32_Relaxed"; } def SImm32AsmOperandClass @@ -1150,6 +1173,10 @@ def immZExt5Plus33 : PatLeaf<(imm), [{ return isUInt<5>(N->getZExtValue() - 33); }]>; +def immZExt5To31 : SDNodeXForm<imm, [{ + return getImm(N, 31 - N->getZExtValue()); +}]>; + // True if (N + 1) fits in 16-bit field. def immSExt16Plus1 : PatLeaf<(imm), [{ return isInt<17>(N->getSExtValue()) && isInt<16>(N->getSExtValue() + 1); @@ -2281,9 +2308,38 @@ def SEQIMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), def : MipsInstAlias<"seq $rd, $imm", (SEQIMacro GPR32Opnd:$rd, GPR32Opnd:$rd, simm32:$imm), 0>, NOT_ASE_CNMIPS; + +def MULImmMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rd, GPR32Opnd:$rs, + simm32_relaxed:$imm), + "mul\t$rd, $rs, $imm">, + ISA_MIPS1_NOT_32R6_64R6; +def MULOMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rd, GPR32Opnd:$rs, + GPR32Opnd:$rt), + "mulo\t$rd, $rs, $rt">, + ISA_MIPS1_NOT_32R6_64R6; +def MULOUMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rd, GPR32Opnd:$rs, + GPR32Opnd:$rt), + "mulou\t$rd, $rs, $rt">, + ISA_MIPS1_NOT_32R6_64R6; + //===----------------------------------------------------------------------===// // Instruction aliases //===----------------------------------------------------------------------===// + +multiclass OneOrTwoOperandMacroImmediateAlias<string Memnomic, + Instruction Opcode, + RegisterOperand RO = GPR32Opnd, + Operand Imm = simm32_relaxed> { + def : MipsInstAlias<!strconcat(Memnomic, " $rs, $rt, $imm"), + (Opcode RO:$rs, + RO:$rt, + Imm:$imm), 0>; + def : MipsInstAlias<!strconcat(Memnomic, " $rs, $imm"), + (Opcode RO:$rs, + RO:$rs, + Imm:$imm), 0>; +} + def : MipsInstAlias<"move $dst, $src", (OR GPR32Opnd:$dst, GPR32Opnd:$src, ZERO), 1>, GPR_32 { @@ -2296,26 +2352,7 @@ def : MipsInstAlias<"move $dst, $src", } def : MipsInstAlias<"bal $offset", (BGEZAL ZERO, brtarget:$offset), 0>, ISA_MIPS1_NOT_32R6_64R6; -def : MipsInstAlias< - "addu $rs, $rt, $imm", - (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rt, simm32_relaxed:$imm), 0>; -def : MipsInstAlias< - "addu $rs, $imm", - (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rs, simm32_relaxed:$imm), 0>; -def : MipsInstAlias< - "add $rs, $rt, $imm", - (ADDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm32_relaxed:$imm), 0>, - ISA_MIPS1_NOT_32R6_64R6; -def : MipsInstAlias< - "add $rs, $imm", - (ADDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm32_relaxed:$imm), 0>, - ISA_MIPS1_NOT_32R6_64R6; -def : MipsInstAlias< - "and $rs, $rt, $imm", - (ANDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm32_relaxed:$imm), 0>; -def : MipsInstAlias< - "and $rs, $imm", - (ANDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm32_relaxed:$imm), 0>; + def : MipsInstAlias<"j $rs", (JR GPR32Opnd:$rs), 0>; let Predicates = [NotInMicroMips] in { def : MipsInstAlias<"jalr $rs", (JALR RA, GPR32Opnd:$rs), 0>; @@ -2343,36 +2380,26 @@ let AdditionalPredicates = [NotInMicroMips] in { "sgtu $$rs, $rt", (SLTu GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; def : MipsInstAlias< - "slt $rs, $rt, $imm", - (SLTi GPR32Opnd:$rs, GPR32Opnd:$rt, simm32_relaxed:$imm), 0>; - def : MipsInstAlias< - "sltu $rt, $rs, $imm", - (SLTiu GPR32Opnd:$rt, GPR32Opnd:$rs, simm32_relaxed:$imm), 0>; - def : MipsInstAlias< - "and $rs, $rt, $imm", - (ANDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm32_relaxed:$imm), 0>; - def : MipsInstAlias< - "and $rs, $imm", - (ANDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm32_relaxed:$imm), 0>; - def : MipsInstAlias< - "xor $rs, $rt, $imm", - (XORi GPR32Opnd:$rs, GPR32Opnd:$rt, simm32_relaxed:$imm), 0>; - def : MipsInstAlias< - "xor $rs, $imm", - (XORi GPR32Opnd:$rs, GPR32Opnd:$rs, simm32_relaxed:$imm), 0>; - def : MipsInstAlias< - "or $rs, $rt, $imm", - (ORi GPR32Opnd:$rs, GPR32Opnd:$rt, simm32_relaxed:$imm), 0>; - def : MipsInstAlias< - "or $rs, $imm", - (ORi GPR32Opnd:$rs, GPR32Opnd:$rs, simm32_relaxed:$imm), 0>; - def : MipsInstAlias< "not $rt, $rs", (NOR GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>; def : MipsInstAlias< "not $rt", (NOR GPR32Opnd:$rt, GPR32Opnd:$rt, ZERO), 0>; def : MipsInstAlias<"nop", (SLL ZERO, ZERO, 0), 1>; + + defm : OneOrTwoOperandMacroImmediateAlias<"add", ADDi>, ISA_MIPS1_NOT_32R6_64R6; + + defm : OneOrTwoOperandMacroImmediateAlias<"addu", ADDiu>; + + defm : OneOrTwoOperandMacroImmediateAlias<"and", ANDi>, GPR_32; + + defm : OneOrTwoOperandMacroImmediateAlias<"or", ORi>, GPR_32; + + defm : OneOrTwoOperandMacroImmediateAlias<"xor", XORi>, GPR_32; + + defm : OneOrTwoOperandMacroImmediateAlias<"slt", SLTi>, GPR_32; + + defm : OneOrTwoOperandMacroImmediateAlias<"sltu", SLTiu>, GPR_32; } def : MipsInstAlias<"mfc0 $rt, $rd", (MFC0 GPR32Opnd:$rt, COP0Opnd:$rd, 0), 0>; def : MipsInstAlias<"mtc0 $rt, $rd", (MTC0 COP0Opnd:$rd, GPR32Opnd:$rt, 0), 0>; @@ -2445,6 +2472,14 @@ let AdditionalPredicates = [NotInMicroMips] in { def : MipsInstAlias<"sdbbp", (SDBBP 0)>, ISA_MIPS32_NOT_32R6_64R6; def : MipsInstAlias<"sync", (SYNC 0), 1>, ISA_MIPS2; + +def : MipsInstAlias<"mulo $rs, $rt", + (MULOMacro GPR32Opnd:$rs, GPR32Opnd:$rs, GPR32Opnd:$rt), 0>, + ISA_MIPS1_NOT_32R6_64R6; +def : MipsInstAlias<"mulou $rs, $rt", + (MULOUMacro GPR32Opnd:$rs, GPR32Opnd:$rs, GPR32Opnd:$rt), 0>, + ISA_MIPS1_NOT_32R6_64R6; + //===----------------------------------------------------------------------===// // Assembler Pseudo Instructions //===----------------------------------------------------------------------===// @@ -2472,9 +2507,12 @@ def JalTwoReg : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins GPR32Opnd:$rs), def JalOneReg : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs), "jal\t$rs"> ; -def NORImm : MipsAsmPseudoInst< - (outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt, simm32:$imm), - "nor\t$rs, $rt, $imm"> ; +class NORIMM_DESC_BASE<RegisterOperand RO, DAGOperand Imm> : + MipsAsmPseudoInst<(outs RO:$rs), (ins RO:$rt, Imm:$imm), + "nor\t$rs, $rt, $imm">; +def NORImm : NORIMM_DESC_BASE<GPR32Opnd, simm32_relaxed>, GPR_32; +def : MipsInstAlias<"nor\t$rs, $imm", (NORImm GPR32Opnd:$rs, GPR32Opnd:$rs, + simm32_relaxed:$imm)>, GPR_32; let hasDelaySlot = 1, isCTI = 1 in { def BneImm : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), @@ -2512,6 +2550,9 @@ class CondBranchImmPseudo<string instr_asm> : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, imm64:$imm, brtarget:$offset), !strconcat(instr_asm, "\t$rs, $imm, $offset")>; +def BEQLImmMacro : CondBranchImmPseudo<"beql">, ISA_MIPS2_NOT_32R6_64R6; +def BNELImmMacro : CondBranchImmPseudo<"bnel">, ISA_MIPS2_NOT_32R6_64R6; + def BLTImmMacro : CondBranchImmPseudo<"blt">; def BLEImmMacro : CondBranchImmPseudo<"ble">; def BGEImmMacro : CondBranchImmPseudo<"bge">; @@ -2535,34 +2576,46 @@ def BGTULImmMacro : CondBranchImmPseudo<"bgtul">, ISA_MIPS2_NOT_32R6_64R6; // Once the tablegen-erated errors are made better, this needs to be fixed and // predicates needs to be restored. -def SDivMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), +def SDivMacro : MipsAsmPseudoInst<(outs GPR32NonZeroOpnd:$rd), (ins GPR32Opnd:$rs, GPR32Opnd:$rt), "div\t$rd, $rs, $rt">, ISA_MIPS1_NOT_32R6_64R6; +def SDivIMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), + (ins GPR32Opnd:$rs, simm32:$imm), + "div\t$rd, $rs, $imm">, + ISA_MIPS1_NOT_32R6_64R6; def UDivMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins GPR32Opnd:$rs, GPR32Opnd:$rt), "divu\t$rd, $rs, $rt">, ISA_MIPS1_NOT_32R6_64R6; -def : MipsInstAlias<"div $rt, $rs", (SDivMacro GPR32Opnd:$rt, GPR32Opnd:$rt, - GPR32Opnd:$rs), 0>, +def UDivIMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), + (ins GPR32Opnd:$rs, simm32:$imm), + "divu\t$rd, $rs, $imm">, + ISA_MIPS1_NOT_32R6_64R6; + + +def : MipsInstAlias<"div $rs, $rt", (SDIV GPR32ZeroOpnd:$rs, + GPR32Opnd:$rt), 0>, + ISA_MIPS1_NOT_32R6_64R6; +def : MipsInstAlias<"div $rs, $rt", (SDivMacro GPR32NonZeroOpnd:$rs, + GPR32NonZeroOpnd:$rs, + GPR32Opnd:$rt), 0>, + ISA_MIPS1_NOT_32R6_64R6; +def : MipsInstAlias<"div $rd, $imm", (SDivIMacro GPR32Opnd:$rd, GPR32Opnd:$rd, + simm32:$imm), 0>, + ISA_MIPS1_NOT_32R6_64R6; + +def : MipsInstAlias<"divu $rt, $rs", (UDIV GPR32ZeroOpnd:$rt, + GPR32Opnd:$rs), 0>, ISA_MIPS1_NOT_32R6_64R6; -def : MipsInstAlias<"divu $rt, $rs", (UDivMacro GPR32Opnd:$rt, GPR32Opnd:$rt, +def : MipsInstAlias<"divu $rt, $rs", (UDivMacro GPR32NonZeroOpnd:$rt, + GPR32NonZeroOpnd:$rt, GPR32Opnd:$rs), 0>, ISA_MIPS1_NOT_32R6_64R6; -def DSDivMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), - (ins GPR32Opnd:$rs, GPR32Opnd:$rt), - "ddiv\t$rd, $rs, $rt">, - ISA_MIPS64_NOT_64R6; -def DUDivMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), - (ins GPR32Opnd:$rs, GPR32Opnd:$rt), - "ddivu\t$rd, $rs, $rt">, - ISA_MIPS64_NOT_64R6; -def : MipsInstAlias<"ddiv $rt, $rs", (DSDivMacro GPR32Opnd:$rt, GPR32Opnd:$rt, - GPR32Opnd:$rs), 0>, - ISA_MIPS64_NOT_64R6; -def : MipsInstAlias<"ddivu $rt, $rs", (DUDivMacro GPR32Opnd:$rt, GPR32Opnd:$rt, - GPR32Opnd:$rs), 0>, - ISA_MIPS64_NOT_64R6; + +def : MipsInstAlias<"divu $rd, $imm", (UDivIMacro GPR32Opnd:$rd, GPR32Opnd:$rd, + simm32:$imm), 0>, + ISA_MIPS1_NOT_32R6_64R6; def Ulh : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins mem:$addr), "ulh\t$rt, $addr">; //, ISA_MIPS1_NOT_32R6_64R6; @@ -2647,30 +2700,40 @@ def : MipsPat<(MipsTailCall (iPTR tglobaladdr:$dst)), def : MipsPat<(MipsTailCall (iPTR texternalsym:$dst)), (TAILCALL texternalsym:$dst)>; // hi/lo relocs -def : MipsPat<(MipsHi tglobaladdr:$in), (LUi tglobaladdr:$in)>; -def : MipsPat<(MipsHi tblockaddress:$in), (LUi tblockaddress:$in)>; -def : MipsPat<(MipsHi tjumptable:$in), (LUi tjumptable:$in)>; -def : MipsPat<(MipsHi tconstpool:$in), (LUi tconstpool:$in)>; -def : MipsPat<(MipsHi tglobaltlsaddr:$in), (LUi tglobaltlsaddr:$in)>; -def : MipsPat<(MipsHi texternalsym:$in), (LUi texternalsym:$in)>; - -def : MipsPat<(MipsLo tglobaladdr:$in), (ADDiu ZERO, tglobaladdr:$in)>; -def : MipsPat<(MipsLo tblockaddress:$in), (ADDiu ZERO, tblockaddress:$in)>; -def : MipsPat<(MipsLo tjumptable:$in), (ADDiu ZERO, tjumptable:$in)>; -def : MipsPat<(MipsLo tconstpool:$in), (ADDiu ZERO, tconstpool:$in)>; -def : MipsPat<(MipsLo tglobaltlsaddr:$in), (ADDiu ZERO, tglobaltlsaddr:$in)>; -def : MipsPat<(MipsLo texternalsym:$in), (ADDiu ZERO, texternalsym:$in)>; - -def : MipsPat<(add GPR32:$hi, (MipsLo tglobaladdr:$lo)), - (ADDiu GPR32:$hi, tglobaladdr:$lo)>; -def : MipsPat<(add GPR32:$hi, (MipsLo tblockaddress:$lo)), - (ADDiu GPR32:$hi, tblockaddress:$lo)>; -def : MipsPat<(add GPR32:$hi, (MipsLo tjumptable:$lo)), - (ADDiu GPR32:$hi, tjumptable:$lo)>; -def : MipsPat<(add GPR32:$hi, (MipsLo tconstpool:$lo)), - (ADDiu GPR32:$hi, tconstpool:$lo)>; -def : MipsPat<(add GPR32:$hi, (MipsLo tglobaltlsaddr:$lo)), - (ADDiu GPR32:$hi, tglobaltlsaddr:$lo)>; +multiclass MipsHiLoRelocs<Instruction Lui, Instruction Addiu, + Register ZeroReg, RegisterOperand GPROpnd> { + def : MipsPat<(MipsHi tglobaladdr:$in), (Lui tglobaladdr:$in)>; + def : MipsPat<(MipsHi tblockaddress:$in), (Lui tblockaddress:$in)>; + def : MipsPat<(MipsHi tjumptable:$in), (Lui tjumptable:$in)>; + def : MipsPat<(MipsHi tconstpool:$in), (Lui tconstpool:$in)>; + def : MipsPat<(MipsHi tglobaltlsaddr:$in), (Lui tglobaltlsaddr:$in)>; + def : MipsPat<(MipsHi texternalsym:$in), (Lui texternalsym:$in)>; + + def : MipsPat<(MipsLo tglobaladdr:$in), (Addiu ZeroReg, tglobaladdr:$in)>; + def : MipsPat<(MipsLo tblockaddress:$in), + (Addiu ZeroReg, tblockaddress:$in)>; + def : MipsPat<(MipsLo tjumptable:$in), (Addiu ZeroReg, tjumptable:$in)>; + def : MipsPat<(MipsLo tconstpool:$in), (Addiu ZeroReg, tconstpool:$in)>; + def : MipsPat<(MipsLo tglobaltlsaddr:$in), + (Addiu ZeroReg, tglobaltlsaddr:$in)>; + def : MipsPat<(MipsLo texternalsym:$in), (Addiu ZeroReg, texternalsym:$in)>; + + def : MipsPat<(add GPROpnd:$hi, (MipsLo tglobaladdr:$lo)), + (Addiu GPROpnd:$hi, tglobaladdr:$lo)>; + def : MipsPat<(add GPROpnd:$hi, (MipsLo tblockaddress:$lo)), + (Addiu GPROpnd:$hi, tblockaddress:$lo)>; + def : MipsPat<(add GPROpnd:$hi, (MipsLo tjumptable:$lo)), + (Addiu GPROpnd:$hi, tjumptable:$lo)>; + def : MipsPat<(add GPROpnd:$hi, (MipsLo tconstpool:$lo)), + (Addiu GPROpnd:$hi, tconstpool:$lo)>; + def : MipsPat<(add GPROpnd:$hi, (MipsLo tglobaltlsaddr:$lo)), + (Addiu GPROpnd:$hi, tglobaltlsaddr:$lo)>; +} + +defm : MipsHiLoRelocs<LUi, ADDiu, ZERO, GPR32Opnd>; + +def : MipsPat<(MipsGotHi tglobaladdr:$in), (LUi tglobaladdr:$in)>; +def : MipsPat<(MipsGotHi texternalsym:$in), (LUi texternalsym:$in)>; // gp_rel relocs def : MipsPat<(add GPR32:$gp, (MipsGPRel tglobaladdr:$in)), diff --git a/lib/Target/Mips/MipsLongBranch.cpp b/lib/Target/Mips/MipsLongBranch.cpp index 1087d0e0140e..100503700a72 100644 --- a/lib/Target/Mips/MipsLongBranch.cpp +++ b/lib/Target/Mips/MipsLongBranch.cpp @@ -13,20 +13,31 @@ // FIXME: Fix pc-region jump instructions which cross 256MB segment boundaries. //===----------------------------------------------------------------------===// -#include "Mips.h" +#include "MCTargetDesc/MipsABIInfo.h" #include "MCTargetDesc/MipsBaseInfo.h" #include "MCTargetDesc/MipsMCNaCl.h" +#include "Mips.h" +#include "MipsInstrInfo.h" #include "MipsMachineFunction.h" +#include "MipsSubtarget.h" #include "MipsTargetMachine.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/IR/Function.h" +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/IR/DebugLoc.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" -#include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetRegisterInfo.h" +#include <cassert> +#include <cstdint> +#include <iterator> using namespace llvm; @@ -47,21 +58,23 @@ static cl::opt<bool> ForceLongBranch( cl::Hidden); namespace { + typedef MachineBasicBlock::iterator Iter; typedef MachineBasicBlock::reverse_iterator ReverseIter; struct MBBInfo { - uint64_t Size, Address; - bool HasLongBranch; - MachineInstr *Br; + uint64_t Size = 0; + uint64_t Address; + bool HasLongBranch = false; + MachineInstr *Br = nullptr; - MBBInfo() : Size(0), HasLongBranch(false), Br(nullptr) {} + MBBInfo() = default; }; class MipsLongBranch : public MachineFunctionPass { - public: static char ID; + MipsLongBranch(TargetMachine &tm) : MachineFunctionPass(ID), TM(tm), IsPIC(TM.isPositionIndependent()), ABI(static_cast<const MipsTargetMachine &>(TM).getABI()) {} @@ -92,13 +105,8 @@ namespace { }; char MipsLongBranch::ID = 0; -} // end of anonymous namespace -/// createMipsLongBranchPass - Returns a pass that converts branches to long -/// branches. -FunctionPass *llvm::createMipsLongBranchPass(MipsTargetMachine &tm) { - return new MipsLongBranch(tm); -} +} // end anonymous namespace /// Iterate over list of Br's operands and search for a MachineBasicBlock /// operand. @@ -530,3 +538,9 @@ bool MipsLongBranch::runOnMachineFunction(MachineFunction &F) { return true; } + +/// createMipsLongBranchPass - Returns a pass that converts branches to long +/// branches. +FunctionPass *llvm::createMipsLongBranchPass(MipsTargetMachine &tm) { + return new MipsLongBranch(tm); +} diff --git a/lib/Target/Mips/MipsMachineFunction.cpp b/lib/Target/Mips/MipsMachineFunction.cpp index d0609b15341d..5bf4c958c7b9 100644 --- a/lib/Target/Mips/MipsMachineFunction.cpp +++ b/lib/Target/Mips/MipsMachineFunction.cpp @@ -7,16 +7,15 @@ // //===----------------------------------------------------------------------===// -#include "MCTargetDesc/MipsBaseInfo.h" -#include "MipsInstrInfo.h" +#include "MCTargetDesc/MipsABIInfo.h" #include "MipsMachineFunction.h" #include "MipsSubtarget.h" #include "MipsTargetMachine.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/IR/Function.h" +#include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetRegisterInfo.h" using namespace llvm; @@ -24,7 +23,7 @@ static cl::opt<bool> FixGlobalBaseReg("mips-fix-global-base-reg", cl::Hidden, cl::init(true), cl::desc("Always use $gp as the global base register.")); -MipsFunctionInfo::~MipsFunctionInfo() {} +MipsFunctionInfo::~MipsFunctionInfo() = default; bool MipsFunctionInfo::globalBaseRegSet() const { return GlobalBaseReg; @@ -101,4 +100,4 @@ int MipsFunctionInfo::getMoveF64ViaSpillFI(const TargetRegisterClass *RC) { return MoveF64ViaSpillFI; } -void MipsFunctionInfo::anchor() { } +void MipsFunctionInfo::anchor() {} diff --git a/lib/Target/Mips/MipsMachineFunction.h b/lib/Target/Mips/MipsMachineFunction.h index c9e5fddc1932..553a66703b26 100644 --- a/lib/Target/Mips/MipsMachineFunction.h +++ b/lib/Target/Mips/MipsMachineFunction.h @@ -1,4 +1,4 @@ -//===-- MipsMachineFunctionInfo.h - Private data used for Mips ----*- C++ -*-=// +//===- MipsMachineFunctionInfo.h - Private data used for Mips ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,12 +15,8 @@ #define LLVM_LIB_TARGET_MIPS_MIPSMACHINEFUNCTION_H #include "Mips16HardFloatInfo.h" -#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/CodeGen/PseudoSourceValue.h" -#include "llvm/Target/TargetFrameLowering.h" -#include "llvm/Target/TargetMachine.h" #include <map> namespace llvm { @@ -29,12 +25,9 @@ namespace llvm { /// Mips target-specific information for each MachineFunction. class MipsFunctionInfo : public MachineFunctionInfo { public: - MipsFunctionInfo(MachineFunction &MF) - : MF(MF), SRetReturnReg(0), GlobalBaseReg(0), VarArgsFrameIndex(0), - CallsEhReturn(false), IsISR(false), SaveS2(false), - MoveF64ViaSpillFI(-1) {} + MipsFunctionInfo(MachineFunction &MF) : MF(MF) {} - ~MipsFunctionInfo(); + ~MipsFunctionInfo() override; unsigned getSRetReturnReg() const { return SRetReturnReg; } void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; } @@ -81,25 +74,26 @@ public: int getMoveF64ViaSpillFI(const TargetRegisterClass *RC); - std::map<const char *, const llvm::Mips16HardFloatInfo::FuncSignature *> + std::map<const char *, const Mips16HardFloatInfo::FuncSignature *> StubsNeeded; private: virtual void anchor(); MachineFunction& MF; + /// SRetReturnReg - Some subtargets require that sret lowering includes /// returning the value of the returned struct in a register. This field /// holds the virtual register into which the sret argument is passed. - unsigned SRetReturnReg; + unsigned SRetReturnReg = 0; /// GlobalBaseReg - keeps track of the virtual register initialized for /// use as the global base register. This is used for PIC in some PIC /// relocation models. - unsigned GlobalBaseReg; + unsigned GlobalBaseReg = 0; /// VarArgsFrameIndex - FrameIndex for start of varargs area. - int VarArgsFrameIndex; + int VarArgsFrameIndex = 0; /// True if function has a byval argument. bool HasByvalArg; @@ -108,25 +102,25 @@ private: unsigned IncomingArgSize; /// CallsEhReturn - Whether the function calls llvm.eh.return. - bool CallsEhReturn; + bool CallsEhReturn = false; /// Frame objects for spilling eh data registers. int EhDataRegFI[4]; /// ISR - Whether the function is an Interrupt Service Routine. - bool IsISR; + bool IsISR = false; /// Frame objects for spilling C0_STATUS, C0_EPC int ISRDataRegFI[2]; // saveS2 - bool SaveS2; + bool SaveS2 = false; /// FrameIndex for expanding BuildPairF64 nodes to spill and reload when the /// O32 FPXX ABI is enabled. -1 is used to denote invalid index. - int MoveF64ViaSpillFI; + int MoveF64ViaSpillFI = -1; }; -} // end of namespace llvm +} // end namespace llvm -#endif +#endif // LLVM_LIB_TARGET_MIPS_MIPSMACHINEFUNCTION_H diff --git a/lib/Target/Mips/MipsOptionRecord.h b/lib/Target/Mips/MipsOptionRecord.h index 23f0b7070d62..4708784063d3 100644 --- a/lib/Target/Mips/MipsOptionRecord.h +++ b/lib/Target/Mips/MipsOptionRecord.h @@ -1,4 +1,4 @@ -//===-- MipsOptionRecord.h - Abstraction for storing information ----------===// +//===- MipsOptionRecord.h - Abstraction for storing information -*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -23,14 +23,16 @@ #include "MCTargetDesc/MipsMCTargetDesc.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCRegisterInfo.h" +#include <cstdint> namespace llvm { + class MipsELFStreamer; -class MCSubtargetInfo; class MipsOptionRecord { public: - virtual ~MipsOptionRecord(){}; + virtual ~MipsOptionRecord() = default; + virtual void EmitMipsOptionRecord() = 0; }; @@ -53,7 +55,8 @@ public: COP2RegClass = &(TRI->getRegClass(Mips::COP2RegClassID)); COP3RegClass = &(TRI->getRegClass(Mips::COP3RegClassID)); } - ~MipsRegInfoRecord() override {} + + ~MipsRegInfoRecord() override = default; void EmitMipsOptionRecord() override; void SetPhysRegUsed(unsigned Reg, const MCRegisterInfo *MCRegInfo); @@ -74,5 +77,7 @@ private: uint32_t ri_cprmask[4]; int64_t ri_gp_value; }; -} // namespace llvm -#endif + +} // end namespace llvm + +#endif // LLVM_LIB_TARGET_MIPS_MIPSOPTIONRECORD_H diff --git a/lib/Target/Mips/MipsOs16.cpp b/lib/Target/Mips/MipsOs16.cpp index 51ac5620f585..670b6c96e78e 100644 --- a/lib/Target/Mips/MipsOs16.cpp +++ b/lib/Target/Mips/MipsOs16.cpp @@ -57,7 +57,7 @@ static bool needsFPFromSig(Function &F) { ; } if (F.arg_size() >=1) { - Argument &Arg = F.getArgumentList().front(); + Argument &Arg = *F.arg_begin(); switch (Arg.getType()->getTypeID()) { case Type::FloatTyID: case Type::DoubleTyID: diff --git a/lib/Target/Mips/MipsRegisterInfo.td b/lib/Target/Mips/MipsRegisterInfo.td index 8c82239ebbd3..ccfdcc89b078 100644 --- a/lib/Target/Mips/MipsRegisterInfo.td +++ b/lib/Target/Mips/MipsRegisterInfo.td @@ -290,6 +290,25 @@ class GPR32Class<list<ValueType> regTypes> : K0, K1, GP, SP, FP, RA)>; def GPR32 : GPR32Class<[i32]>; + +def GPR32ZERO : RegisterClass<"Mips", [i32], 32, (add + // Reserved + ZERO)>; + +def GPR32NONZERO : RegisterClass<"Mips", [i32], 32, (add + // Reserved + AT, + // Return Values and Arguments + V0, V1, A0, A1, A2, A3, + // Not preserved across procedure calls + T0, T1, T2, T3, T4, T5, T6, T7, + // Callee save + S0, S1, S2, S3, S4, S5, S6, S7, + // Not preserved across procedure calls + T8, T9, + // Reserved + K0, K1, GP, SP, FP, RA)>; + def DSPR : GPR32Class<[v4i8, v2i16]>; def GPRMM16 : RegisterClass<"Mips", [i32], 32, (add @@ -317,7 +336,7 @@ def GPRMM16MoveP : RegisterClass<"Mips", [i32], 32, (add S0, S2, S3, S4)>; def GPR64 : RegisterClass<"Mips", [i64], 64, (add -// Reserved + // Reserved ZERO_64, AT_64, // Return Values and Arguments V0_64, V1_64, A0_64, A1_64, A2_64, A3_64, @@ -479,6 +498,16 @@ def GPR64AsmOperand : MipsAsmRegOperand { let PredicateMethod = "isGPRAsmReg"; } +def GPR32ZeroAsmOperand : MipsAsmRegOperand { + let Name = "GPR32ZeroAsmReg"; + let PredicateMethod = "isGPRZeroAsmReg"; +} + +def GPR32NonZeroAsmOperand : MipsAsmRegOperand { + let Name = "GPR32NonZeroAsmReg"; + let PredicateMethod = "isGPRNonZeroAsmReg"; +} + def GPR32AsmOperand : MipsAsmRegOperand { let Name = "GPR32AsmReg"; let PredicateMethod = "isGPRAsmReg"; @@ -550,6 +579,14 @@ def MSACtrlAsmOperand : MipsAsmRegOperand { let Name = "MSACtrlAsmReg"; } +def GPR32ZeroOpnd : RegisterOperand<GPR32ZERO> { + let ParserMatchClass = GPR32ZeroAsmOperand; +} + +def GPR32NonZeroOpnd : RegisterOperand<GPR32NONZERO> { + let ParserMatchClass = GPR32NonZeroAsmOperand; +} + def GPR32Opnd : RegisterOperand<GPR32> { let ParserMatchClass = GPR32AsmOperand; } diff --git a/lib/Target/Mips/MipsSEFrameLowering.cpp b/lib/Target/Mips/MipsSEFrameLowering.cpp index 4996d070eb29..ef8d18c6deb1 100644 --- a/lib/Target/Mips/MipsSEFrameLowering.cpp +++ b/lib/Target/Mips/MipsSEFrameLowering.cpp @@ -11,27 +11,42 @@ // //===----------------------------------------------------------------------===// -#include "MipsSEFrameLowering.h" -#include "MCTargetDesc/MipsBaseInfo.h" +#include "MCTargetDesc/MipsABIInfo.h" #include "MipsMachineFunction.h" +#include "MipsRegisterInfo.h" +#include "MipsSEFrameLowering.h" #include "MipsSEInstrInfo.h" #include "MipsSubtarget.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/RegisterScavenging.h" -#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DebugLoc.h" #include "llvm/IR/Function.h" -#include "llvm/Target/TargetOptions.h" +#include "llvm/MC/MCDwarf.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MachineLocation.h" +#include "llvm/Support/CodeGen.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetSubtargetInfo.h" +#include <cassert> +#include <cstdint> +#include <utility> +#include <vector> using namespace llvm; -namespace { -typedef MachineBasicBlock::iterator Iter; - static std::pair<unsigned, unsigned> getMFHiLoOpc(unsigned Src) { if (Mips::ACC64RegClass.contains(Src)) return std::make_pair((unsigned)Mips::PseudoMFHI, @@ -47,6 +62,8 @@ static std::pair<unsigned, unsigned> getMFHiLoOpc(unsigned Src) { return std::make_pair(0, 0); } +namespace { + /// Helper class to expand pseudos. class ExpandPseudo { public: @@ -54,6 +71,8 @@ public: bool expand(); private: + typedef MachineBasicBlock::iterator Iter; + bool expandInstr(MachineBasicBlock &MBB, Iter I); void expandLoadCCond(MachineBasicBlock &MBB, Iter I); void expandStoreCCond(MachineBasicBlock &MBB, Iter I); @@ -74,7 +93,8 @@ private: const MipsSEInstrInfo &TII; const MipsRegisterInfo &RegInfo; }; -} + +} // end anonymous namespace ExpandPseudo::ExpandPseudo(MachineFunction &MF_) : MF(MF_), MRI(MF.getRegInfo()), @@ -419,7 +439,7 @@ void MipsSEFrameLowering::emitPrologue(MachineFunction &MF, const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); - if (CSI.size()) { + if (!CSI.empty()) { // Find the instruction past the last instruction that saves a callee-saved // register to the stack. for (unsigned i = 0; i < CSI.size(); ++i) @@ -471,7 +491,7 @@ void MipsSEFrameLowering::emitPrologue(MachineFunction &MF, } else { // Reg is either in GPR32 or FGR32. unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( - nullptr, MRI->getDwarfRegNum(Reg, 1), Offset)); + nullptr, MRI->getDwarfRegNum(Reg, true), Offset)); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); } @@ -534,7 +554,6 @@ void MipsSEFrameLowering::emitPrologue(MachineFunction &MF, void MipsSEFrameLowering::emitInterruptPrologueStub( MachineFunction &MF, MachineBasicBlock &MBB) const { - MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); MachineBasicBlock::iterator MBBI = MBB.begin(); DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); @@ -722,7 +741,6 @@ void MipsSEFrameLowering::emitEpilogue(MachineFunction &MF, void MipsSEFrameLowering::emitInterruptEpilogueStub( MachineFunction &MF, MachineBasicBlock &MBB) const { - MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); @@ -820,7 +838,6 @@ spillCalleeSavedRegisters(MachineBasicBlock &MBB, bool MipsSEFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { const MachineFrameInfo &MFI = MF.getFrameInfo(); - // Reserve call frame if the size of the maximum call frame fits into 16-bit // immediate field and there are no variable sized objects on the stack. // Make sure the second register scavenger spill slot can be accessed with one diff --git a/lib/Target/Mips/MipsSEFrameLowering.h b/lib/Target/Mips/MipsSEFrameLowering.h index 63cd3cebc56a..bf30deb1905e 100644 --- a/lib/Target/Mips/MipsSEFrameLowering.h +++ b/lib/Target/Mips/MipsSEFrameLowering.h @@ -1,4 +1,4 @@ -//===-- MipsSEFrameLowering.h - Mips32/64 frame lowering --------*- C++ -*-===// +//===- MipsSEFrameLowering.h - Mips32/64 frame lowering ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,6 +15,8 @@ #define LLVM_LIB_TARGET_MIPS_MIPSSEFRAMELOWERING_H #include "MipsFrameLowering.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include <vector> namespace llvm { @@ -47,6 +49,7 @@ private: void emitInterruptPrologueStub(MachineFunction &MF, MachineBasicBlock &MBB) const; }; -} // End llvm namespace -#endif +} // end namespace llvm + +#endif // LLVM_LIB_TARGET_MIPS_MIPSSEFRAMELOWERING_H diff --git a/lib/Target/Mips/MipsSEISelDAGToDAG.cpp b/lib/Target/Mips/MipsSEISelDAGToDAG.cpp index 92d3c001df94..c9cf9363b8c9 100644 --- a/lib/Target/Mips/MipsSEISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsSEISelDAGToDAG.cpp @@ -97,11 +97,13 @@ bool MipsSEDAGToDAGISel::replaceUsesWithZeroReg(MachineRegisterInfo *MRI, // Check if MI is "addiu $dst, $zero, 0" or "daddiu $dst, $zero, 0". if ((MI.getOpcode() == Mips::ADDiu) && (MI.getOperand(1).getReg() == Mips::ZERO) && + (MI.getOperand(2).isImm()) && (MI.getOperand(2).getImm() == 0)) { DstReg = MI.getOperand(0).getReg(); ZeroReg = Mips::ZERO; } else if ((MI.getOpcode() == Mips::DADDiu) && (MI.getOperand(1).getReg() == Mips::ZERO_64) && + (MI.getOperand(2).isImm()) && (MI.getOperand(2).getImm() == 0)) { DstReg = MI.getOperand(0).getReg(); ZeroReg = Mips::ZERO_64; @@ -690,7 +692,7 @@ bool MipsSEDAGToDAGISel::selectVSplatMaskL(SDValue N, SDValue &Imm) const { // as the original value. if (ImmValue == ~(~ImmValue & ~(~ImmValue + 1))) { - Imm = CurDAG->getTargetConstant(ImmValue.countPopulation(), SDLoc(N), + Imm = CurDAG->getTargetConstant(ImmValue.countPopulation() - 1, SDLoc(N), EltTy); return true; } @@ -722,7 +724,7 @@ bool MipsSEDAGToDAGISel::selectVSplatMaskR(SDValue N, SDValue &Imm) const { // Extract the run of set bits starting with bit zero, and test that the // result is the same as the original value if (ImmValue == (ImmValue & ~(ImmValue + 1))) { - Imm = CurDAG->getTargetConstant(ImmValue.countPopulation(), SDLoc(N), + Imm = CurDAG->getTargetConstant(ImmValue.countPopulation() - 1, SDLoc(N), EltTy); return true; } @@ -932,6 +934,9 @@ bool MipsSEDAGToDAGISel::trySelect(SDNode *Node) { // same set/ of registers. Similarly, ldi.h isn't capable of producing { // 0x00000000, 0x00000001, 0x00000000, 0x00000001 } but 'ldi.d wd, 1' can. + const MipsABIInfo &ABI = + static_cast<const MipsTargetMachine &>(TM).getABI(); + BuildVectorSDNode *BVN = cast<BuildVectorSDNode>(Node); APInt SplatValue, SplatUndef; unsigned SplatBitSize; @@ -969,13 +974,233 @@ bool MipsSEDAGToDAGISel::trySelect(SDNode *Node) { break; } - if (!SplatValue.isSignedIntN(10)) - return false; - - SDValue Imm = CurDAG->getTargetConstant(SplatValue, DL, - ViaVecTy.getVectorElementType()); + SDNode *Res; - SDNode *Res = CurDAG->getMachineNode(LdiOp, DL, ViaVecTy, Imm); + // If we have a signed 10 bit integer, we can splat it directly. + // + // If we have something bigger we can synthesize the value into a GPR and + // splat from there. + if (SplatValue.isSignedIntN(10)) { + SDValue Imm = CurDAG->getTargetConstant(SplatValue, DL, + ViaVecTy.getVectorElementType()); + + Res = CurDAG->getMachineNode(LdiOp, DL, ViaVecTy, Imm); + } else if (SplatValue.isSignedIntN(16) && + ((ABI.IsO32() && SplatBitSize < 64) || + (ABI.IsN32() || ABI.IsN64()))) { + // Only handle signed 16 bit values when the element size is GPR width. + // MIPS64 can handle all the cases but MIPS32 would need to handle + // negative cases specifically here. Instead, handle those cases as + // 64bit values. + + bool Is32BitSplat = ABI.IsO32() || SplatBitSize < 64; + const unsigned ADDiuOp = Is32BitSplat ? Mips::ADDiu : Mips::DADDiu; + const MVT SplatMVT = Is32BitSplat ? MVT::i32 : MVT::i64; + SDValue ZeroVal = CurDAG->getRegister( + Is32BitSplat ? Mips::ZERO : Mips::ZERO_64, SplatMVT); + + const unsigned FILLOp = + SplatBitSize == 16 + ? Mips::FILL_H + : (SplatBitSize == 32 ? Mips::FILL_W + : (SplatBitSize == 64 ? Mips::FILL_D : 0)); + + assert(FILLOp != 0 && "Unknown FILL Op for splat synthesis!"); + assert((!ABI.IsO32() || (FILLOp != Mips::FILL_D)) && + "Attempting to use fill.d on MIPS32!"); + + const unsigned Lo = SplatValue.getLoBits(16).getZExtValue(); + SDValue LoVal = CurDAG->getTargetConstant(Lo, DL, SplatMVT); + + Res = CurDAG->getMachineNode(ADDiuOp, DL, SplatMVT, ZeroVal, LoVal); + Res = CurDAG->getMachineNode(FILLOp, DL, ViaVecTy, SDValue(Res, 0)); + + } else if (SplatValue.isSignedIntN(32) && SplatBitSize == 32) { + // Only handle the cases where the splat size agrees with the size + // of the SplatValue here. + const unsigned Lo = SplatValue.getLoBits(16).getZExtValue(); + const unsigned Hi = SplatValue.lshr(16).getLoBits(16).getZExtValue(); + SDValue ZeroVal = CurDAG->getRegister(Mips::ZERO, MVT::i32); + + SDValue LoVal = CurDAG->getTargetConstant(Lo, DL, MVT::i32); + SDValue HiVal = CurDAG->getTargetConstant(Hi, DL, MVT::i32); + + if (Hi) + Res = CurDAG->getMachineNode(Mips::LUi, DL, MVT::i32, HiVal); + + if (Lo) + Res = CurDAG->getMachineNode(Mips::ORi, DL, MVT::i32, + 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)); + + } else if (SplatValue.isSignedIntN(32) && SplatBitSize == 64 && + (ABI.IsN32() || ABI.IsN64())) { + // N32 and N64 can perform some tricks that O32 can't for signed 32 bit + // integers due to having 64bit registers. lui will cause the necessary + // zero/sign extension. + const unsigned Lo = SplatValue.getLoBits(16).getZExtValue(); + const unsigned Hi = SplatValue.lshr(16).getLoBits(16).getZExtValue(); + SDValue ZeroVal = CurDAG->getRegister(Mips::ZERO, MVT::i32); + + SDValue LoVal = CurDAG->getTargetConstant(Lo, DL, MVT::i32); + SDValue HiVal = CurDAG->getTargetConstant(Hi, DL, MVT::i32); + + if (Hi) + Res = CurDAG->getMachineNode(Mips::LUi, DL, MVT::i32, HiVal); + + if (Lo) + Res = CurDAG->getMachineNode(Mips::ORi, DL, MVT::i32, + Hi ? SDValue(Res, 0) : ZeroVal, LoVal); + + Res = CurDAG->getMachineNode( + Mips::SUBREG_TO_REG, DL, MVT::i64, + CurDAG->getTargetConstant(((Hi >> 15) & 0x1), DL, MVT::i64), + SDValue(Res, 0), + CurDAG->getTargetConstant(Mips::sub_32, DL, MVT::i64)); + + Res = + CurDAG->getMachineNode(Mips::FILL_D, DL, MVT::v2i64, SDValue(Res, 0)); + + } else if (SplatValue.isSignedIntN(64)) { + // If we have a 64 bit Splat value, we perform a similar sequence to the + // above: + // + // MIPS32: MIPS64: + // lui $res, %highest(val) lui $res, %highest(val) + // ori $res, $res, %higher(val) ori $res, $res, %higher(val) + // lui $res2, %hi(val) lui $res2, %hi(val) + // ori $res2, %res2, %lo(val) ori $res2, %res2, %lo(val) + // $res3 = fill $res2 dinsu $res, $res2, 0, 32 + // $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. + // + // FIXME: Implement the preferred sequence for MIPS64R6: + // + // MIPS64R6: + // ori $res, $zero, %lo(val) + // daui $res, $res, %hi(val) + // dahi $res, $res, %higher(val) + // dati $res, $res, %highest(cal) + // fill.d $res + // + + const unsigned Lo = SplatValue.getLoBits(16).getZExtValue(); + const unsigned Hi = SplatValue.lshr(16).getLoBits(16).getZExtValue(); + const unsigned Higher = SplatValue.lshr(32).getLoBits(16).getZExtValue(); + const unsigned Highest = SplatValue.lshr(48).getLoBits(16).getZExtValue(); + + SDValue LoVal = CurDAG->getTargetConstant(Lo, DL, MVT::i32); + SDValue HiVal = CurDAG->getTargetConstant(Hi, DL, MVT::i32); + SDValue HigherVal = CurDAG->getTargetConstant(Higher, DL, MVT::i32); + SDValue HighestVal = CurDAG->getTargetConstant(Highest, DL, MVT::i32); + SDValue ZeroVal = CurDAG->getRegister(Mips::ZERO, MVT::i32); + + // Independent of whether we're targeting MIPS64 or not, the basic + // operations are the same. Also, directly use the $zero register if + // the 16 bit chunk is zero. + // + // For optimization purposes we always synthesize the splat value as + // an i32 value, then if we're targetting MIPS64, use SUBREG_TO_REG + // just before combining the values with dinsu to produce an i64. This + // enables SelectionDAG to aggressively share components of splat values + // where possible. + // + // FIXME: This is the general constant synthesis problem. This code + // should be factored out into a class shared between all the + // classes that need it. Specifically, for a splat size of 64 + // bits that's a negative number we can do better than LUi/ORi + // for the upper 32bits. + + if (Hi) + Res = CurDAG->getMachineNode(Mips::LUi, DL, MVT::i32, HiVal); + + if (Lo) + Res = CurDAG->getMachineNode(Mips::ORi, DL, MVT::i32, + Hi ? SDValue(Res, 0) : ZeroVal, LoVal); + + SDNode *HiRes; + if (Highest) + HiRes = CurDAG->getMachineNode(Mips::LUi, DL, MVT::i32, HighestVal); + + if (Higher) + HiRes = CurDAG->getMachineNode(Mips::ORi, DL, MVT::i32, + Highest ? SDValue(HiRes, 0) : ZeroVal, + HigherVal); + + + if (ABI.IsO32()) { + Res = CurDAG->getMachineNode(Mips::FILL_W, DL, MVT::v4i32, + (Hi || Lo) ? SDValue(Res, 0) : ZeroVal); + + Res = CurDAG->getMachineNode( + Mips::INSERT_W, DL, MVT::v4i32, SDValue(Res, 0), + (Highest || Higher) ? SDValue(HiRes, 0) : ZeroVal, + CurDAG->getTargetConstant(1, DL, MVT::i32)); + + const TargetLowering *TLI = getTargetLowering(); + const TargetRegisterClass *RC = + TLI->getRegClassFor(ViaVecTy.getSimpleVT()); + + Res = CurDAG->getMachineNode( + Mips::COPY_TO_REGCLASS, DL, ViaVecTy, SDValue(Res, 0), + CurDAG->getTargetConstant(RC->getID(), DL, MVT::i32)); + + Res = CurDAG->getMachineNode( + Mips::SPLATI_D, DL, MVT::v2i64, SDValue(Res, 0), + CurDAG->getTargetConstant(0, DL, MVT::i32)); + } else if (ABI.IsN64() || ABI.IsN32()) { + + SDValue Zero64Val = CurDAG->getRegister(Mips::ZERO_64, MVT::i64); + const bool HiResNonZero = Highest || Higher; + const bool ResNonZero = Hi || Lo; + + if (HiResNonZero) + HiRes = CurDAG->getMachineNode( + Mips::SUBREG_TO_REG, DL, MVT::i64, + CurDAG->getTargetConstant(((Highest >> 15) & 0x1), DL, MVT::i64), + SDValue(HiRes, 0), + CurDAG->getTargetConstant(Mips::sub_32, DL, MVT::i64)); + + if (ResNonZero) + Res = CurDAG->getMachineNode( + Mips::SUBREG_TO_REG, DL, MVT::i64, + CurDAG->getTargetConstant(((Hi >> 15) & 0x1), DL, MVT::i64), + SDValue(Res, 0), + CurDAG->getTargetConstant(Mips::sub_32, DL, MVT::i64)); + + // We have 3 cases: + // The HiRes is nonzero but Res is $zero => dsll32 HiRes, 0 + // The Res is nonzero but HiRes is $zero => dinsu Res, $zero, 32, 32 + // Both are non zero => dinsu Res, HiRes, 32, 32 + // + // The obvious "missing" case is when both are zero, but that case is + // handled by the ldi case. + if (ResNonZero) { + SDValue Ops[4] = {HiResNonZero ? SDValue(HiRes, 0) : Zero64Val, + CurDAG->getTargetConstant(64, DL, MVT::i32), + CurDAG->getTargetConstant(32, DL, MVT::i32), + SDValue(Res, 0)}; + + Res = CurDAG->getMachineNode(Mips::DINSU, DL, MVT::i64, Ops); + } else if (HiResNonZero) { + Res = CurDAG->getMachineNode( + Mips::DSLL32, DL, MVT::i64, SDValue(HiRes, 0), + CurDAG->getTargetConstant(0, DL, MVT::i32)); + } else + llvm_unreachable( + "Zero splat value handled by non-zero 64bit splat synthesis!"); + + Res = CurDAG->getMachineNode(Mips::FILL_D, DL, MVT::v2i64, SDValue(Res, 0)); + } else + llvm_unreachable("Unknown ABI in MipsISelDAGToDAG!"); + + } else + return false; if (ResVecTy != ViaVecTy) { // If LdiOp is writing to a different register class to ResVecTy, then diff --git a/lib/Target/Mips/MipsSEISelLowering.cpp b/lib/Target/Mips/MipsSEISelLowering.cpp index f28e8b36fdbc..e2da8477295b 100644 --- a/lib/Target/Mips/MipsSEISelLowering.cpp +++ b/lib/Target/Mips/MipsSEISelLowering.cpp @@ -1123,7 +1123,8 @@ MipsSETargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { case ISD::MUL: return performMULCombine(N, DAG, DCI, this); case ISD::SHL: - return performSHLCombine(N, DAG, DCI, Subtarget); + Val = performSHLCombine(N, DAG, DCI, Subtarget); + break; case ISD::SRA: return performSRACombine(N, DAG, DCI, Subtarget); case ISD::SRL: @@ -1643,7 +1644,7 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, if (Op->getConstantOperandVal(3) >= EltTy.getSizeInBits()) report_fatal_error("Immediate out of range"); APInt Mask = APInt::getHighBitsSet(EltTy.getSizeInBits(), - Op->getConstantOperandVal(3)); + Op->getConstantOperandVal(3) + 1); return DAG.getNode(ISD::VSELECT, DL, VecTy, DAG.getConstant(Mask, DL, VecTy, true), Op->getOperand(2), Op->getOperand(1)); @@ -1658,7 +1659,7 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, if (Op->getConstantOperandVal(3) >= EltTy.getSizeInBits()) report_fatal_error("Immediate out of range"); APInt Mask = APInt::getLowBitsSet(EltTy.getSizeInBits(), - Op->getConstantOperandVal(3)); + Op->getConstantOperandVal(3) + 1); return DAG.getNode(ISD::VSELECT, DL, VecTy, DAG.getConstant(Mask, DL, VecTy, true), Op->getOperand(2), Op->getOperand(1)); @@ -2529,11 +2530,10 @@ SDValue MipsSETargetLowering::lowerBUILD_VECTOR(SDValue Op, SplatBitSize != 64) return SDValue(); - // If the value fits into a simm10 then we can use ldi.[bhwd] - // However, if it isn't an integer type we will have to bitcast from an - // integer type first. Also, if there are any undefs, we must lower them - // to defined values first. - if (ResTy.isInteger() && !HasAnyUndefs && SplatValue.isSignedIntN(10)) + // If the value isn't an integer type we will have to bitcast + // from an integer type first. Also, if there are any undefs, we must + // lower them to defined values first. + if (ResTy.isInteger() && !HasAnyUndefs) return Op; EVT ViaVecTy; @@ -3628,7 +3628,7 @@ MipsSETargetLowering::emitLD_F16_PSEUDO(MachineInstr &MI, MachineInstrBuilder MIB = BuildMI(*BB, MI, DL, TII->get(UsingMips32 ? Mips::LH : Mips::LH64), Rt); for (unsigned i = 1; i < MI.getNumOperands(); i++) - MIB.addOperand(MI.getOperand(i)); + MIB.add(MI.getOperand(i)); BuildMI(*BB, MI, DL, TII->get(Mips::FILL_H), Wd).addReg(Rt); diff --git a/lib/Target/Mips/MipsSEInstrInfo.cpp b/lib/Target/Mips/MipsSEInstrInfo.cpp index ea703d0edd96..91e712a7a54e 100644 --- a/lib/Target/Mips/MipsSEInstrInfo.cpp +++ b/lib/Target/Mips/MipsSEInstrInfo.cpp @@ -540,11 +540,20 @@ unsigned MipsSEInstrInfo::getAnalyzableBrOpc(unsigned Opc) const { void MipsSEInstrInfo::expandRetRA(MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { + + MachineInstrBuilder MIB; if (Subtarget.isGP64bit()) - BuildMI(MBB, I, I->getDebugLoc(), get(Mips::PseudoReturn64)) - .addReg(Mips::RA_64); + MIB = BuildMI(MBB, I, I->getDebugLoc(), get(Mips::PseudoReturn64)) + .addReg(Mips::RA_64, RegState::Undef); else - BuildMI(MBB, I, I->getDebugLoc(), get(Mips::PseudoReturn)).addReg(Mips::RA); + MIB = BuildMI(MBB, I, I->getDebugLoc(), get(Mips::PseudoReturn)) + .addReg(Mips::RA, RegState::Undef); + + // Retain any imp-use flags. + for (auto & MO : I->operands()) { + if (MO.isImplicit()) + MIB.add(MO); + } } void MipsSEInstrInfo::expandERet(MachineBasicBlock &MBB, diff --git a/lib/Target/Mips/MipsSubtarget.cpp b/lib/Target/Mips/MipsSubtarget.cpp index 3e7570ff46ed..8f5ecadecdea 100644 --- a/lib/Target/Mips/MipsSubtarget.cpp +++ b/lib/Target/Mips/MipsSubtarget.cpp @@ -70,8 +70,8 @@ MipsSubtarget::MipsSubtarget(const Triple &TT, const std::string &CPU, 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), HasEVA(false), TM(TM), - TargetTriple(TT), TSInfo(), + Os16(Mips_Os16), HasMSA(false), UseTCCInDIV(false), HasSym32(false), + HasEVA(false), TM(TM), TargetTriple(TT), TSInfo(), InstrInfo( MipsInstrInfo::create(initializeSubtargetDependencies(CPU, FS, TM))), FrameLowering(MipsFrameLowering::create(*this)), @@ -117,6 +117,9 @@ MipsSubtarget::MipsSubtarget(const Triple &TT, const std::string &CPU, if (NoABICalls && TM.isPositionIndependent()) report_fatal_error("position-independent code requires '-mabicalls'"); + if (isABI_N64() && !TM.isPositionIndependent() && !hasSym32()) + NoABICalls = true; + // Set UseSmallSection. UseSmallSection = GPOpt; if (!NoABICalls && GPOpt) { diff --git a/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h index 38d3cee70477..cca2cb8a4660 100644 --- a/lib/Target/Mips/MipsSubtarget.h +++ b/lib/Target/Mips/MipsSubtarget.h @@ -142,6 +142,9 @@ class MipsSubtarget : public MipsGenSubtargetInfo { // UseTCCInDIV -- Enables the use of trapping in the assembler. bool UseTCCInDIV; + // Sym32 -- On Mips64 symbols are 32 bits. + bool HasSym32; + // HasEVA -- supports EVA ASE. bool HasEVA; @@ -229,7 +232,11 @@ public: unsigned getGPRSizeInBytes() const { return isGP64bit() ? 8 : 4; } bool isPTR64bit() const { return IsPTR64bit; } bool isPTR32bit() const { return !IsPTR64bit; } + bool hasSym32() const { + return (HasSym32 && isABI_N64()) || isABI_N32() || isABI_O32(); + } bool isSingleFloat() const { return IsSingleFloat; } + bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); } bool hasVFPU() const { return HasVFPU; } bool inMips16Mode() const { return InMips16Mode; } bool inMips16ModeDefault() const { @@ -271,6 +278,8 @@ public: bool isTargetNaCl() const { return TargetTriple.isOSNaCl(); } + bool isXRaySupported() const override { return true; } + // for now constant islands are on for the whole compilation unit but we only // really use them if in addition we are in mips16 mode static bool useConstantIslands(); diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp index bb48188e3b87..a45a9c4b41c3 100644 --- a/lib/Target/Mips/MipsTargetMachine.cpp +++ b/lib/Target/Mips/MipsTargetMachine.cpp @@ -11,27 +11,30 @@ // //===----------------------------------------------------------------------===// -#include "MipsTargetMachine.h" +#include "MCTargetDesc/MipsABIInfo.h" +#include "MCTargetDesc/MipsMCTargetDesc.h" #include "Mips.h" -#include "Mips16FrameLowering.h" #include "Mips16ISelDAGToDAG.h" -#include "Mips16ISelLowering.h" -#include "Mips16InstrInfo.h" -#include "MipsFrameLowering.h" -#include "MipsInstrInfo.h" -#include "MipsSEFrameLowering.h" #include "MipsSEISelDAGToDAG.h" -#include "MipsSEISelLowering.h" -#include "MipsSEInstrInfo.h" +#include "MipsSubtarget.h" #include "MipsTargetObjectFile.h" +#include "MipsTargetMachine.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/CodeGen/BasicTTIImpl.h" +#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/TargetPassConfig.h" -#include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/Attributes.h" +#include "llvm/IR/Function.h" +#include "llvm/Support/CodeGen.h" #include "llvm/Support/Debug.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Transforms/Scalar.h" +#include "llvm/Target/TargetOptions.h" +#include <string> using namespace llvm; @@ -48,7 +51,7 @@ extern "C" void LLVMInitializeMipsTarget() { static std::string computeDataLayout(const Triple &TT, StringRef CPU, const TargetOptions &Options, bool isLittle) { - std::string Ret = ""; + std::string Ret; MipsABIInfo ABI = MipsABIInfo::computeTargetABI(TT, CPU, Options.MCOptions); // There are both little and big endian mips. @@ -102,7 +105,7 @@ MipsTargetMachine::MipsTargetMachine(const Target &T, const Triple &TT, : LLVMTargetMachine(T, computeDataLayout(TT, CPU, Options, isLittle), TT, CPU, FS, Options, getEffectiveRelocModel(CM, RM), CM, OL), - isLittle(isLittle), TLOF(make_unique<MipsTargetObjectFile>()), + isLittle(isLittle), TLOF(llvm::make_unique<MipsTargetObjectFile>()), ABI(MipsABIInfo::computeTargetABI(TT, CPU, Options.MCOptions)), Subtarget(nullptr), DefaultSubtarget(TT, CPU, FS, isLittle, *this), NoMips16Subtarget(TT, CPU, FS.empty() ? "-mips16" : FS.str() + ",-mips16", @@ -113,9 +116,9 @@ MipsTargetMachine::MipsTargetMachine(const Target &T, const Triple &TT, initAsmInfo(); } -MipsTargetMachine::~MipsTargetMachine() {} +MipsTargetMachine::~MipsTargetMachine() = default; -void MipsebTargetMachine::anchor() { } +void MipsebTargetMachine::anchor() {} MipsebTargetMachine::MipsebTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, @@ -125,7 +128,7 @@ MipsebTargetMachine::MipsebTargetMachine(const Target &T, const Triple &TT, CodeGenOpt::Level OL) : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {} -void MipselTargetMachine::anchor() { } +void MipselTargetMachine::anchor() {} MipselTargetMachine::MipselTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, @@ -182,10 +185,10 @@ void MipsTargetMachine::resetSubtarget(MachineFunction *MF) { Subtarget = const_cast<MipsSubtarget *>(getSubtargetImpl(*MF->getFunction())); MF->setSubtarget(Subtarget); - return; } namespace { + /// Mips Code Generator Pass Configuration Options. class MipsPassConfig : public TargetPassConfig { public: @@ -209,11 +212,10 @@ public: void addIRPasses() override; bool addInstSelector() override; void addPreEmitPass() override; - void addPreRegAlloc() override; - }; -} // namespace + +} // end anonymous namespace TargetPassConfig *MipsTargetMachine::createPassConfig(PassManagerBase &PM) { return new MipsPassConfig(this, PM); diff --git a/lib/Target/Mips/MipsTargetMachine.h b/lib/Target/Mips/MipsTargetMachine.h index e4cf17e2abd8..140d7133f879 100644 --- a/lib/Target/Mips/MipsTargetMachine.h +++ b/lib/Target/Mips/MipsTargetMachine.h @@ -1,4 +1,4 @@ -//===-- MipsTargetMachine.h - Define TargetMachine for Mips -----*- C++ -*-===// +//===- MipsTargetMachine.h - Define TargetMachine for Mips ------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,15 +16,14 @@ #include "MCTargetDesc/MipsABIInfo.h" #include "MipsSubtarget.h" -#include "llvm/CodeGen/BasicTTIImpl.h" -#include "llvm/CodeGen/Passes.h" -#include "llvm/CodeGen/SelectionDAGISel.h" -#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/CodeGen.h" #include "llvm/Target/TargetMachine.h" +#include <memory> namespace llvm { -class formatted_raw_ostream; -class MipsRegisterInfo; class MipsTargetMachine : public LLVMTargetMachine { bool isLittle; @@ -73,6 +72,7 @@ public: /// class MipsebTargetMachine : public MipsTargetMachine { virtual void anchor(); + public: MipsebTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, @@ -84,6 +84,7 @@ public: /// class MipselTargetMachine : public MipsTargetMachine { virtual void anchor(); + public: MipselTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, @@ -91,6 +92,6 @@ public: CodeGenOpt::Level OL); }; -} // End llvm namespace +} // end namespace llvm -#endif +#endif // LLVM_LIB_TARGET_MIPS_MIPSTARGETMACHINE_H |