diff options
Diffstat (limited to 'lib/Target/Mips')
129 files changed, 3784 insertions, 1458 deletions
diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index d2fed6861477..1f7d095bf49b 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -1,9 +1,8 @@ //===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -13,6 +12,7 @@ #include "MCTargetDesc/MipsMCExpr.h" #include "MCTargetDesc/MipsMCTargetDesc.h" #include "MipsTargetStreamer.h" +#include "TargetInfo/MipsTargetInfo.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" @@ -29,6 +29,7 @@ #include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/MC/MCParser/MCAsmParserExtension.h" +#include "llvm/MC/MCParser/MCAsmParserUtils.h" #include "llvm/MC/MCParser/MCParsedAsmOperand.h" #include "llvm/MC/MCParser/MCTargetAsmParser.h" #include "llvm/MC/MCSectionELF.h" @@ -65,10 +66,7 @@ class MCInstrInfo; } // end namespace llvm -static cl::opt<bool> -EmitJalrReloc("mips-jalr-reloc", cl::Hidden, - cl::desc("MIPS: Emit R_{MICRO}MIPS_JALR relocation with jalr"), - cl::init(true)); +extern cl::opt<bool> EmitJalrReloc; namespace { @@ -148,6 +146,7 @@ class MipsAsmParser : public MCTargetAsmParser { bool IsPicEnabled; bool IsCpRestoreSet; int CpRestoreOffset; + unsigned GPReg; unsigned CpSaveLocation; /// If true, then CpSaveLocation is a register, otherwise it's an offset. bool CpSaveLocationIsRegister; @@ -277,6 +276,15 @@ class MipsAsmParser : public MCTargetAsmParser { bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI); + bool expandSge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); + + bool expandSgeImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); + + bool expandSgtImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); + bool expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI); bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, @@ -304,6 +312,9 @@ class MipsAsmParser : public MCTargetAsmParser { bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI, bool IsLoad); + bool expandStoreDM1Macro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); + bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI); @@ -324,6 +335,7 @@ class MipsAsmParser : public MCTargetAsmParser { bool parseSetFeature(uint64_t Feature); bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup. bool parseDirectiveCpLoad(SMLoc Loc); + bool parseDirectiveCpLocal(SMLoc Loc); bool parseDirectiveCpRestore(SMLoc Loc); bool parseDirectiveCPSetup(); bool parseDirectiveCPReturn(); @@ -517,6 +529,7 @@ public: IsCpRestoreSet = false; CpRestoreOffset = -1; + GPReg = ABI.GetGlobalPtr(); const Triple &TheTriple = sti.getTargetTriple(); IsLittleEndian = TheTriple.isLittleEndian(); @@ -895,14 +908,6 @@ private: .getRegister(RegIdx.Index); } - /// Coerce the register to FGRH32 and return the real register for the current - /// target. - unsigned getFGRH32Reg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!"); - return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID) - .getRegister(RegIdx.Index); - } - /// Coerce the register to FCC and return the real register for the current /// target. unsigned getFCCReg() const { @@ -1100,11 +1105,6 @@ public: "registers"); } - void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(getFGRH32Reg())); - } - void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::createReg(getFCCReg())); @@ -2043,7 +2043,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, const MCExpr *Lo16RelocExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext()); - TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP, + TOut.emitRRX(Mips::LW, Mips::T9, GPReg, MCOperand::createExpr(Got16RelocExpr), IDLoc, STI); TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9, MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI); @@ -2057,7 +2057,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext()); TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, - Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc, + GPReg, MCOperand::createExpr(GotDispRelocExpr), IDLoc, STI); } } else { @@ -2068,7 +2068,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, const MCExpr *Call16RelocExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext()); - TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP, + TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, GPReg, MCOperand::createExpr(Call16RelocExpr), IDLoc, STI); } @@ -2485,6 +2485,19 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, case Mips::NORImm: case Mips::NORImm64: return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; + case Mips::SGE: + case Mips::SGEU: + return expandSge(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; + case Mips::SGEImm: + case Mips::SGEUImm: + case Mips::SGEImm64: + case Mips::SGEUImm64: + return expandSgeImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; + case Mips::SGTImm: + case Mips::SGTUImm: + case Mips::SGTImm64: + case Mips::SGTUImm64: + return expandSgtImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; case Mips::SLTImm64: if (isInt<16>(Inst.getOperand(2).getImm())) { Inst.setOpcode(Mips::SLTi64); @@ -2553,6 +2566,10 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, Inst.getOpcode() == Mips::LDMacro) ? MER_Fail : MER_Success; + case Mips::SDC1_M1: + return expandStoreDM1Macro(Inst, IDLoc, Out, STI) + ? MER_Fail + : MER_Success; case Mips::SEQMacro: return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; case Mips::SEQIMacro: @@ -2879,8 +2896,8 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr, ELF::STB_LOCAL))) { const MCExpr *CallExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext()); - TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(), - MCOperand::createExpr(CallExpr), IDLoc, STI); + TOut.emitRRX(Mips::LW, DstReg, GPReg, MCOperand::createExpr(CallExpr), + IDLoc, STI); return false; } @@ -2919,8 +2936,8 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr, TmpReg = ATReg; } - TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(), - MCOperand::createExpr(GotExpr), IDLoc, STI); + TOut.emitRRX(Mips::LW, TmpReg, GPReg, MCOperand::createExpr(GotExpr), IDLoc, + STI); if (LoExpr) TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), @@ -2955,8 +2972,8 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr, ELF::STB_LOCAL))) { const MCExpr *CallExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext()); - TOut.emitRRX(Mips::LD, DstReg, ABI.GetGlobalPtr(), - MCOperand::createExpr(CallExpr), IDLoc, STI); + TOut.emitRRX(Mips::LD, DstReg, GPReg, MCOperand::createExpr(CallExpr), + IDLoc, STI); return false; } @@ -2998,8 +3015,8 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr, TmpReg = ATReg; } - TOut.emitRRX(Mips::LD, TmpReg, ABI.GetGlobalPtr(), - MCOperand::createExpr(GotExpr), IDLoc, STI); + TOut.emitRRX(Mips::LD, TmpReg, GPReg, MCOperand::createExpr(GotExpr), IDLoc, + STI); if (LoExpr) TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), @@ -3229,10 +3246,10 @@ bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext()); if(isABI_O32() || isABI_N32()) { - TOut.emitRRX(Mips::LW, ATReg, Mips::GP, MCOperand::createExpr(GotExpr), + TOut.emitRRX(Mips::LW, ATReg, GPReg, MCOperand::createExpr(GotExpr), IDLoc, STI); } else { //isABI_N64() - TOut.emitRRX(Mips::LD, ATReg, Mips::GP, MCOperand::createExpr(GotExpr), + TOut.emitRRX(Mips::LD, ATReg, GPReg, MCOperand::createExpr(GotExpr), IDLoc, STI); } } else { //!IsPicEnabled @@ -4293,6 +4310,143 @@ bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, return false; } +bool MipsAsmParser::expandSge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + 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).isReg() && "Invalid instruction operand."); + + unsigned DstReg = Inst.getOperand(0).getReg(); + unsigned SrcReg = Inst.getOperand(1).getReg(); + unsigned OpReg = Inst.getOperand(2).getReg(); + unsigned OpCode; + + warnIfNoMacro(IDLoc); + + switch (Inst.getOpcode()) { + case Mips::SGE: + OpCode = Mips::SLT; + break; + case Mips::SGEU: + OpCode = Mips::SLTu; + break; + default: + llvm_unreachable("unexpected 'sge' opcode"); + } + + // $SrcReg >= $OpReg is equal to (not ($SrcReg < $OpReg)) + TOut.emitRRR(OpCode, DstReg, SrcReg, OpReg, IDLoc, STI); + TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI); + + return false; +} + +bool MipsAsmParser::expandSgeImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + 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."); + + unsigned DstReg = Inst.getOperand(0).getReg(); + unsigned SrcReg = Inst.getOperand(1).getReg(); + int64_t ImmValue = Inst.getOperand(2).getImm(); + unsigned OpRegCode, OpImmCode; + + warnIfNoMacro(IDLoc); + + switch (Inst.getOpcode()) { + case Mips::SGEImm: + case Mips::SGEImm64: + OpRegCode = Mips::SLT; + OpImmCode = Mips::SLTi; + break; + case Mips::SGEUImm: + case Mips::SGEUImm64: + OpRegCode = Mips::SLTu; + OpImmCode = Mips::SLTiu; + break; + default: + llvm_unreachable("unexpected 'sge' opcode with immediate"); + } + + // $SrcReg >= Imm is equal to (not ($SrcReg < Imm)) + if (isInt<16>(ImmValue)) { + // Use immediate version of STL. + TOut.emitRRI(OpImmCode, DstReg, SrcReg, ImmValue, IDLoc, STI); + TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI); + } else { + unsigned ImmReg = DstReg; + if (DstReg == SrcReg) { + unsigned ATReg = getATReg(Inst.getLoc()); + if (!ATReg) + return true; + ImmReg = ATReg; + } + + if (loadImmediate(ImmValue, ImmReg, Mips::NoRegister, isInt<32>(ImmValue), + false, IDLoc, Out, STI)) + return true; + + TOut.emitRRR(OpRegCode, DstReg, SrcReg, ImmReg, IDLoc, STI); + TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI); + } + + return false; +} + +bool MipsAsmParser::expandSgtImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + 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."); + + unsigned DstReg = Inst.getOperand(0).getReg(); + unsigned SrcReg = Inst.getOperand(1).getReg(); + unsigned ImmReg = DstReg; + int64_t ImmValue = Inst.getOperand(2).getImm(); + unsigned OpCode; + + warnIfNoMacro(IDLoc); + + switch (Inst.getOpcode()) { + case Mips::SGTImm: + case Mips::SGTImm64: + OpCode = Mips::SLT; + break; + case Mips::SGTUImm: + case Mips::SGTUImm64: + OpCode = Mips::SLTu; + break; + default: + llvm_unreachable("unexpected 'sgt' opcode with immediate"); + } + + if (DstReg == SrcReg) { + unsigned ATReg = getATReg(Inst.getLoc()); + if (!ATReg) + return true; + ImmReg = ATReg; + } + + if (loadImmediate(ImmValue, ImmReg, Mips::NoRegister, isInt<32>(ImmValue), + false, IDLoc, Out, STI)) + return true; + + // $SrcReg > $ImmReg is equal to $ImmReg < $SrcReg + TOut.emitRRR(OpCode, DstReg, ImmReg, SrcReg, IDLoc, STI); + + return false; +} + bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI) { @@ -4859,61 +5013,110 @@ bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, return false; } + +// Expand 's.d $<reg> offset($reg2)' to 'swc1 $<reg+1>, offset($reg2); +// swc1 $<reg>, offset+4($reg2)' +// or if little endian to 'swc1 $<reg>, offset($reg2); +// swc1 $<reg+1>, offset+4($reg2)' +// for Mips1. +bool MipsAsmParser::expandStoreDM1Macro(MCInst &Inst, SMLoc IDLoc, + MCStreamer &Out, + const MCSubtargetInfo *STI) { + if (!isABI_O32()) + return true; + + warnIfNoMacro(IDLoc); + + MipsTargetStreamer &TOut = getTargetStreamer(); + unsigned Opcode = Mips::SWC1; + unsigned FirstReg = Inst.getOperand(0).getReg(); + unsigned SecondReg = nextReg(FirstReg); + unsigned BaseReg = Inst.getOperand(1).getReg(); + if (!SecondReg) + return true; + + warnIfRegIndexIsAT(FirstReg, IDLoc); + + assert(Inst.getOperand(2).isImm() && + "Offset for macro is not immediate!"); + + MCOperand &FirstOffset = Inst.getOperand(2); + signed NextOffset = FirstOffset.getImm() + 4; + MCOperand SecondOffset = MCOperand::createImm(NextOffset); + + if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset)) + return true; + + if (!IsLittleEndian) + std::swap(FirstReg, SecondReg); + + TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI); + TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI); + + return false; +} + bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, 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).isReg() && "Invalid instruction operand."); + + unsigned DstReg = Inst.getOperand(0).getReg(); + unsigned SrcReg = Inst.getOperand(1).getReg(); + unsigned OpReg = Inst.getOperand(2).getReg(); warnIfNoMacro(IDLoc); - MipsTargetStreamer &TOut = getTargetStreamer(); - if (Inst.getOperand(1).getReg() != Mips::ZERO && - Inst.getOperand(2).getReg() != Mips::ZERO) { - TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(), - Inst.getOperand(1).getReg(), Inst.getOperand(2).getReg(), - IDLoc, STI); - TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), - Inst.getOperand(0).getReg(), 1, IDLoc, STI); + if (SrcReg != Mips::ZERO && OpReg != Mips::ZERO) { + TOut.emitRRR(Mips::XOR, DstReg, SrcReg, OpReg, IDLoc, STI); + TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 1, IDLoc, STI); return false; } - unsigned Reg = 0; - if (Inst.getOperand(1).getReg() == Mips::ZERO) { - Reg = Inst.getOperand(2).getReg(); - } else { - Reg = Inst.getOperand(1).getReg(); - } - TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), Reg, 1, IDLoc, STI); + unsigned Reg = SrcReg == Mips::ZERO ? OpReg : SrcReg; + TOut.emitRRI(Mips::SLTiu, DstReg, Reg, 1, IDLoc, STI); return false; } bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI) { - warnIfNoMacro(IDLoc); MipsTargetStreamer &TOut = getTargetStreamer(); - unsigned Opc; + assert(Inst.getNumOperands() == 3 && "Invalid operand count"); + assert(Inst.getOperand(0).isReg() && + Inst.getOperand(1).isReg() && + Inst.getOperand(2).isImm() && "Invalid instruction operand."); + + unsigned DstReg = Inst.getOperand(0).getReg(); + unsigned SrcReg = Inst.getOperand(1).getReg(); int64_t Imm = Inst.getOperand(2).getImm(); - unsigned Reg = Inst.getOperand(1).getReg(); + + warnIfNoMacro(IDLoc); if (Imm == 0) { - TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), - Inst.getOperand(1).getReg(), 1, IDLoc, STI); + TOut.emitRRI(Mips::SLTiu, DstReg, SrcReg, 1, IDLoc, STI); return false; - } else { + } - if (Reg == Mips::ZERO) { - Warning(IDLoc, "comparison is always false"); - TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu, - Inst.getOperand(0).getReg(), Reg, Reg, IDLoc, STI); - return false; - } + if (SrcReg == Mips::ZERO) { + Warning(IDLoc, "comparison is always false"); + TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu, + DstReg, SrcReg, SrcReg, IDLoc, STI); + return false; + } - if (Imm > -0x8000 && Imm < 0) { - Imm = -Imm; - Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu; - } else { - Opc = Mips::XORi; - } + unsigned Opc; + if (Imm > -0x8000 && Imm < 0) { + Imm = -Imm; + Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu; + } else { + Opc = Mips::XORi; } + if (!isUInt<16>(Imm)) { unsigned ATReg = getATReg(IDLoc); if (!ATReg) @@ -4923,17 +5126,13 @@ bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, Out, STI)) return true; - TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(), - Inst.getOperand(1).getReg(), ATReg, IDLoc, STI); - TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), - Inst.getOperand(0).getReg(), 1, IDLoc, STI); + TOut.emitRRR(Mips::XOR, DstReg, SrcReg, ATReg, IDLoc, STI); + TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 1, IDLoc, STI); return false; } - TOut.emitRRI(Opc, Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(), - Imm, IDLoc, STI); - TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), - Inst.getOperand(0).getReg(), 1, IDLoc, STI); + TOut.emitRRI(Opc, DstReg, SrcReg, Imm, IDLoc, STI); + TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 1, IDLoc, STI); return false; } @@ -6325,7 +6524,7 @@ bool MipsAsmParser::parseBracketSuffix(StringRef Name, return false; } -static std::string MipsMnemonicSpellCheck(StringRef S, uint64_t FBS, +static std::string MipsMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS, unsigned VariantID = 0); bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, @@ -6338,7 +6537,7 @@ bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, // Check if we have valid mnemonic if (!mnemonicIsValid(Name, 0)) { - uint64_t FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); + FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); std::string Suggestion = MipsMnemonicSpellCheck(Name, FBS); return Error(NameLoc, "unknown instruction" + Suggestion); } @@ -6807,7 +7006,6 @@ bool MipsAsmParser::parseSetHardFloatDirective() { bool MipsAsmParser::parseSetAssignment() { StringRef Name; - const MCExpr *Value; MCAsmParser &Parser = getParser(); if (Parser.parseIdentifier(Name)) @@ -6825,17 +7023,16 @@ bool MipsAsmParser::parseSetAssignment() { RegisterSets[Name] = Parser.getTok(); Parser.Lex(); // Eat identifier. getContext().getOrCreateSymbol(Name); - } else if (!Parser.parseExpression(Value)) { - // Parse assignment of an expression including - // symbolic registers: - // .set $tmp, $BB0-$BB1 - // .set r2, $f2 - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - Sym->setVariableValue(Value); - } else { - return reportParseError("expected valid expression after comma"); + return false; } + MCSymbol *Sym; + const MCExpr *Value; + if (MCParserUtils::parseAssignmentExpression(Name, /* allow_redef */ true, + Parser, Sym, Value)) + return true; + Sym->setVariableValue(Value); + return false; } @@ -7047,6 +7244,40 @@ bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) { return false; } +bool MipsAsmParser::parseDirectiveCpLocal(SMLoc Loc) { + if (!isABI_N32() && !isABI_N64()) { + reportParseError(".cplocal is allowed only in N32 or N64 mode"); + return false; + } + + SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg; + OperandMatchResultTy ResTy = parseAnyRegister(Reg); + if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) { + reportParseError("expected register containing global pointer"); + return false; + } + + MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]); + if (!RegOpnd.isGPRAsmReg()) { + reportParseError(RegOpnd.getStartLoc(), "invalid register"); + return false; + } + + // If this is not the end of the statement, report an error. + if (getLexer().isNot(AsmToken::EndOfStatement)) { + reportParseError("unexpected token, expected end of statement"); + return false; + } + getParser().Lex(); // Consume the EndOfStatement. + + unsigned NewReg = RegOpnd.getGPR32Reg(); + if (IsPicEnabled) + GPReg = NewReg; + + getTargetStreamer().emitDirectiveCpLocal(NewReg); + return false; +} + bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) { MCAsmParser &Parser = getParser(); @@ -7897,6 +8128,10 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { parseDirectiveCpRestore(DirectiveID.getLoc()); return false; } + if (IDVal == ".cplocal") { + parseDirectiveCpLocal(DirectiveID.getLoc()); + return false; + } if (IDVal == ".ent") { StringRef SymbolName; diff --git a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp index 27b27ff1e1e2..ef13507fe63a 100644 --- a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -1,9 +1,8 @@ //===- MipsDisassembler.cpp - Disassembler for Mips -----------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -13,6 +12,7 @@ #include "MCTargetDesc/MipsMCTargetDesc.h" #include "Mips.h" +#include "TargetInfo/MipsTargetInfo.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCDisassembler/MCDisassembler.h" @@ -541,15 +541,6 @@ static DecodeStatus DecodeMovePRegPair(MCInst &Inst, unsigned RegPair, static DecodeStatus DecodeMovePOperands(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder); -namespace llvm { - -Target &getTheMipselTarget(); -Target &getTheMipsTarget(); -Target &getTheMips64Target(); -Target &getTheMips64elTarget(); - -} // end namespace llvm - static MCDisassembler *createMipsDisassembler( const Target &T, const MCSubtargetInfo &STI, diff --git a/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp b/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp index 4a2b75b9ae46..fca1149453c9 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp @@ -1,9 +1,8 @@ //===- MipsABIFlagsSection.cpp - Mips ELF ABI Flags Section ---------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h b/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h index 68bf3829aab5..239e55495e9d 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h +++ b/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h @@ -1,9 +1,8 @@ //===- MipsABIFlagsSection.h - Mips ELF ABI Flags Section -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp b/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp index 18d7dd99be34..bdd190fc17c9 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp @@ -1,9 +1,8 @@ //===---- MipsABIInfo.cpp - Information about MIPS ABI's ------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -15,6 +14,13 @@ using namespace llvm; +// Note: this option is defined here to be visible from libLLVMMipsAsmParser +// and libLLVMMipsCodeGen +cl::opt<bool> +EmitJalrReloc("mips-jalr-reloc", cl::Hidden, + cl::desc("MIPS: Emit R_{MICRO}MIPS_JALR relocation with jalr"), + cl::init(true)); + namespace { static const MCPhysReg O32IntRegs[4] = {Mips::A0, Mips::A1, Mips::A2, Mips::A3}; diff --git a/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h b/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h index 9372a3c2bb1f..534e6573b63c 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h +++ b/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h @@ -1,9 +1,8 @@ //===---- MipsABIInfo.h - Information about MIPS ABI's --------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp index 265d1141cb0b..859f9cbbca07 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp @@ -1,9 +1,8 @@ //===-- MipsAsmBackend.cpp - Mips Asm Backend ----------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -303,7 +302,7 @@ void MipsAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, Optional<MCFixupKind> MipsAsmBackend::getFixupKind(StringRef Name) const { return StringSwitch<Optional<MCFixupKind>>(Name) - .Case("R_MIPS_NONE", (MCFixupKind)Mips::fixup_Mips_NONE) + .Case("R_MIPS_NONE", FK_NONE) .Case("R_MIPS_32", FK_Data_4) .Case("R_MIPS_GOT_PAGE", (MCFixupKind)Mips::fixup_Mips_GOT_PAGE) .Case("R_MIPS_CALL_HI16", (MCFixupKind)Mips::fixup_Mips_CALL_HI16) @@ -351,7 +350,6 @@ getFixupKindInfo(MCFixupKind Kind) const { // MipsFixupKinds.h. // // name offset bits flags - { "fixup_Mips_NONE", 0, 0, 0 }, { "fixup_Mips_16", 0, 16, 0 }, { "fixup_Mips_32", 0, 32, 0 }, { "fixup_Mips_REL32", 0, 32, 0 }, @@ -431,7 +429,6 @@ getFixupKindInfo(MCFixupKind Kind) const { // MipsFixupKinds.h. // // name offset bits flags - { "fixup_Mips_NONE", 0, 0, 0 }, { "fixup_Mips_16", 16, 16, 0 }, { "fixup_Mips_32", 0, 32, 0 }, { "fixup_Mips_REL32", 0, 32, 0 }, diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h index 30359132e92b..4d7e36995ae4 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h +++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h @@ -1,9 +1,8 @@ //===-- MipsAsmBackend.h - Mips Asm Backend ------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h b/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h index a90db2384c46..6d8cb264158f 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h +++ b/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h @@ -1,9 +1,8 @@ //===-- MipsBaseInfo.h - Top level definitions for MIPS MC ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -89,7 +88,10 @@ namespace MipsII { MO_GOT_HI16, MO_GOT_LO16, MO_CALL_HI16, - MO_CALL_LO16 + MO_CALL_LO16, + + /// Helper operand used to generate R_MIPS_JALR + MO_JALR }; enum { diff --git a/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp index 8ace2895d681..cf7bae98a27f 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp @@ -1,9 +1,8 @@ //===-- MipsELFObjectWriter.cpp - Mips ELF Writer -------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -223,7 +222,7 @@ unsigned MipsELFObjectWriter::getRelocType(MCContext &Ctx, unsigned Kind = (unsigned)Fixup.getKind(); switch (Kind) { - case Mips::fixup_Mips_NONE: + case FK_NONE: return ELF::R_MIPS_NONE; case FK_Data_1: Ctx.reportError(Fixup.getLoc(), diff --git a/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp b/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp index 21b01e850967..1b83e9445fb5 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp @@ -1,9 +1,8 @@ //===-------- MipsELFStreamer.cpp - ELF Object Output ---------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -35,7 +34,7 @@ MipsELFStreamer::MipsELFStreamer(MCContext &Context, } void MipsELFStreamer::EmitInstruction(const MCInst &Inst, - const MCSubtargetInfo &STI, bool) { + const MCSubtargetInfo &STI) { MCELFStreamer::EmitInstruction(Inst, STI); MCContext &Context = getContext(); diff --git a/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h b/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h index 56a0ff96c7bd..2febfbc69b6f 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h +++ b/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h @@ -1,9 +1,8 @@ //===- MipsELFStreamer.h - ELF Object Output --------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -42,8 +41,7 @@ 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, - bool = false) override; + void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override; /// Overriding this function allows us to record all labels that should be /// marked as microMIPS. Based on this data marking is done in diff --git a/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h b/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h index eedad16dddc3..b83d822bd8d0 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h +++ b/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h @@ -1,9 +1,8 @@ //===-- MipsFixupKinds.h - Mips Specific Fixup Entries ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -23,11 +22,8 @@ namespace Mips { // in MipsAsmBackend.cpp. // enum Fixups { - // Branch fixups resulting in R_MIPS_NONE. - fixup_Mips_NONE = FirstTargetFixupKind, - // Branch fixups resulting in R_MIPS_16. - fixup_Mips_16, + fixup_Mips_16 = FirstTargetFixupKind, // Pure 32 bit data fixup resulting in - R_MIPS_32. fixup_Mips_32, diff --git a/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp b/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.cpp index 73732a40bb8a..fb290a8e3f26 100644 --- a/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.cpp @@ -1,9 +1,8 @@ //===-- MipsInstPrinter.cpp - Convert Mips MCInst to assembly syntax ------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -12,8 +11,8 @@ //===----------------------------------------------------------------------===// #include "MipsInstPrinter.h" -#include "MCTargetDesc/MipsMCExpr.h" #include "MipsInstrInfo.h" +#include "MipsMCExpr.h" #include "llvm/ADT/StringExtras.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" diff --git a/lib/Target/Mips/InstPrinter/MipsInstPrinter.h b/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.h index f02443ee21d3..a34a5c1d6418 100644 --- a/lib/Target/Mips/InstPrinter/MipsInstPrinter.h +++ b/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.h @@ -1,9 +1,8 @@ //=== MipsInstPrinter.h - Convert Mips MCInst to assembly syntax -*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -11,8 +10,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIB_TARGET_MIPS_INSTPRINTER_MIPSINSTPRINTER_H -#define LLVM_LIB_TARGET_MIPS_INSTPRINTER_MIPSINSTPRINTER_H +#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSINSTPRINTER_H +#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSINSTPRINTER_H #include "llvm/MC/MCInstPrinter.h" namespace llvm { diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp index 1506b4a83649..ec78158d387d 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp @@ -1,9 +1,8 @@ //===-- MipsMCAsmInfo.cpp - Mips Asm Properties ---------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h index d4ccf0349c16..867f4d223de4 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h +++ b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h @@ -1,9 +1,8 @@ //===-- MipsMCAsmInfo.h - Mips Asm Info ------------------------*- C++ -*--===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index f43a4d980f92..759a7fdb32b8 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -1,9 +1,8 @@ //===-- MipsMCCodeEmitter.cpp - Convert Mips Code to Machine Code ---------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -186,7 +185,7 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, // Check for unimplemented opcodes. // Unfortunately in MIPS both NOP and SLL will come in with Binary == 0 // so we have to special check for them. - unsigned Opcode = TmpInst.getOpcode(); + const unsigned Opcode = TmpInst.getOpcode(); if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) && (Opcode != Mips::SLL_MM) && (Opcode != Mips::SLL_MMR6) && !Binary) llvm_unreachable("unimplemented opcode in encodeInstruction()"); @@ -209,7 +208,6 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, if (Fixups.size() > N) Fixups.pop_back(); - Opcode = NewOpcode; TmpInst.setOpcode (NewOpcode); Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); } @@ -614,8 +612,9 @@ getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups, llvm_unreachable("Unhandled fixup kind!"); break; case MipsMCExpr::MEK_DTPREL: - llvm_unreachable("MEK_DTPREL is used for TLS DIEExpr only"); - break; + // MEK_DTPREL is used for marking TLS DIEExpr only + // and contains a regular sub-expression. + return getExprOpValue(MipsExpr->getSubExpr(), Fixups, STI); case MipsMCExpr::MEK_CALL_HI16: FixupKind = Mips::fixup_Mips_CALL_HI16; break; diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h index 09d50d4776ba..ff6e1d62b05f 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h +++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h @@ -1,9 +1,8 @@ //===- MipsMCCodeEmitter.h - Convert Mips Code to Machine Code --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp index 99857e083c6c..680806c4deb2 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp @@ -1,9 +1,8 @@ //===-- MipsMCExpr.cpp - Mips specific MC expression classes --------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -44,8 +43,10 @@ void MipsMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { llvm_unreachable("MEK_None and MEK_Special are invalid"); break; case MEK_DTPREL: - llvm_unreachable("MEK_DTPREL is used for TLS DIEExpr only"); - break; + // MEK_DTPREL is used for marking TLS DIEExpr only + // and contains a regular sub-expression. + getSubExpr()->print(OS, MAI, true); + return; case MEK_CALL_HI16: OS << "%call_hi"; break; @@ -161,7 +162,9 @@ MipsMCExpr::evaluateAsRelocatableImpl(MCValue &Res, case MEK_Special: llvm_unreachable("MEK_None and MEK_Special are invalid"); case MEK_DTPREL: - llvm_unreachable("MEK_DTPREL is used for TLS DIEExpr only"); + // MEK_DTPREL is used for marking TLS DIEExpr only + // and contains a regular sub-expression. + return getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup); case MEK_DTPREL_HI: case MEK_DTPREL_LO: case MEK_GOT: @@ -249,9 +252,6 @@ void MipsMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { case MEK_Special: llvm_unreachable("MEK_None and MEK_Special are invalid"); break; - case MEK_DTPREL: - llvm_unreachable("MEK_DTPREL is used for TLS DIEExpr only"); - break; case MEK_CALL_HI16: case MEK_CALL_LO16: case MEK_GOT: @@ -274,6 +274,7 @@ void MipsMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { if (const MipsMCExpr *E = dyn_cast<const MipsMCExpr>(getSubExpr())) E->fixELFSymbolsInTLSFixups(Asm); break; + case MEK_DTPREL: case MEK_DTPREL_HI: case MEK_DTPREL_LO: case MEK_TLSLDM: diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h b/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h index bf3274ab5d17..edc12e87e9b6 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h +++ b/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h @@ -1,9 +1,8 @@ //===- MipsMCExpr.h - Mips specific MC expression classes -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h b/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h index 988629ed1bca..ad5aff6552f6 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h +++ b/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h @@ -1,9 +1,8 @@ //===-- MipsMCNaCl.h - NaCl-related declarations --------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp index a8cd7b0d9b03..ddeec03ba784 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp @@ -1,9 +1,8 @@ //===-- MipsMCTargetDesc.cpp - Mips Target Descriptions -------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -12,12 +11,13 @@ //===----------------------------------------------------------------------===// #include "MipsMCTargetDesc.h" -#include "InstPrinter/MipsInstPrinter.h" #include "MipsAsmBackend.h" #include "MipsELFStreamer.h" +#include "MipsInstPrinter.h" #include "MipsMCAsmInfo.h" #include "MipsMCNaCl.h" #include "MipsTargetStreamer.h" +#include "TargetInfo/MipsTargetInfo.h" #include "llvm/ADT/Triple.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCELFStreamer.h" @@ -85,7 +85,7 @@ static MCAsmInfo *createMipsMCAsmInfo(const MCRegisterInfo &MRI, MCAsmInfo *MAI = new MipsMCAsmInfo(TT); unsigned SP = MRI.getDwarfRegNum(Mips::SP, true); - MCCFIInstruction Inst = MCCFIInstruction::createDefCfa(nullptr, SP, 0); + MCCFIInstruction Inst = MCCFIInstruction::createDefCfaRegister(nullptr, SP); MAI->addInitialFrameState(Inst); return MAI; diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h index 4fc174ab5871..809be99ff3f4 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h +++ b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h @@ -1,9 +1,8 @@ //===-- MipsMCTargetDesc.h - Mips Target Descriptions -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -33,11 +32,6 @@ class Triple; class raw_ostream; class raw_pwrite_stream; -Target &getTheMipsTarget(); -Target &getTheMipselTarget(); -Target &getTheMips64Target(); -Target &getTheMips64elTarget(); - MCCodeEmitter *createMipsMCCodeEmitterEB(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, MCContext &Ctx); diff --git a/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp b/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp index 6bf62ea618b4..c050db8a17fd 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp @@ -1,9 +1,8 @@ //===-- MipsNaClELFStreamer.cpp - ELF Object Output for Mips NaCl ---------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -144,8 +143,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, - bool) override { + void EmitInstruction(const MCInst &Inst, + const MCSubtargetInfo &STI) override { // Sandbox indirect jumps. if (isIndirectJump(Inst)) { if (PendingCall) diff --git a/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp b/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp index 2d84528e7469..b4ebb9d18b72 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp @@ -1,9 +1,8 @@ //===- MipsOptionRecord.cpp - Abstraction for storing information ---------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp index 58f9717e1cc6..e3bdb3b140a8 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -1,9 +1,8 @@ //===-- MipsTargetStreamer.cpp - Mips Target Streamer Methods -------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -12,7 +11,7 @@ //===----------------------------------------------------------------------===// #include "MipsTargetStreamer.h" -#include "InstPrinter/MipsInstPrinter.h" +#include "MipsInstPrinter.h" #include "MCTargetDesc/MipsABIInfo.h" #include "MipsELFStreamer.h" #include "MipsMCExpr.h" @@ -36,7 +35,7 @@ static cl::opt<bool> RoundSectionSizes( } // end anonymous namespace MipsTargetStreamer::MipsTargetStreamer(MCStreamer &S) - : MCTargetStreamer(S), ModuleDirectiveAllowed(true) { + : MCTargetStreamer(S), GPReg(Mips::GP), ModuleDirectiveAllowed(true) { GPRInfoSet = FPRInfoSet = FrameInfoSet = false; } void MipsTargetStreamer::emitDirectiveSetMicroMips() {} @@ -107,6 +106,23 @@ void MipsTargetStreamer::emitDirectiveSetDsp() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetDspr2() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetNoDsp() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveCpLoad(unsigned RegNo) {} +void MipsTargetStreamer::emitDirectiveCpLocal(unsigned RegNo) { + // .cplocal $reg + // This directive forces to use the alternate register for context pointer. + // For example + // .cplocal $4 + // jal foo + // expands to + // ld $25, %call16(foo)($4) + // jalr $25 + + if (!getABI().IsN32() && !getABI().IsN64()) + return; + + GPReg = RegNo; + + forbidModuleDirective(); +} bool MipsTargetStreamer::emitDirectiveCpRestore( int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc, const MCSubtargetInfo *STI) { @@ -258,8 +274,7 @@ void MipsTargetStreamer::emitNop(SMLoc IDLoc, const MCSubtargetInfo *STI) { /// Emit the $gp restore operation for .cprestore. void MipsTargetStreamer::emitGPRestore(int Offset, SMLoc IDLoc, const MCSubtargetInfo *STI) { - emitLoadWithImmOffset(Mips::LW, Mips::GP, Mips::SP, Offset, Mips::GP, IDLoc, - STI); + emitLoadWithImmOffset(Mips::LW, GPReg, Mips::SP, Offset, GPReg, IDLoc, STI); } /// Emit a store instruction with an immediate offset. @@ -666,6 +681,12 @@ void MipsTargetAsmStreamer::emitDirectiveCpLoad(unsigned RegNo) { forbidModuleDirective(); } +void MipsTargetAsmStreamer::emitDirectiveCpLocal(unsigned RegNo) { + OS << "\t.cplocal\t$" + << StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << "\n"; + MipsTargetStreamer::emitDirectiveCpLocal(RegNo); +} + bool MipsTargetAsmStreamer::emitDirectiveCpRestore( int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc, const MCSubtargetInfo *STI) { @@ -700,8 +721,11 @@ void MipsTargetAsmStreamer::emitDirectiveCpreturn(unsigned SaveLocation, } void MipsTargetAsmStreamer::emitDirectiveModuleFP() { - OS << "\t.module\tfp="; - OS << ABIFlagsSection.getFpABIString(ABIFlagsSection.getFpABI()) << "\n"; + MipsABIFlagsSection::FpABIKind FpABI = ABIFlagsSection.getFpABI(); + if (FpABI == MipsABIFlagsSection::FpABIKind::SOFT) + OS << "\t.module\tsoftfloat\n"; + else + OS << "\t.module\tfp=" << ABIFlagsSection.getFpABIString(FpABI) << "\n"; } void MipsTargetAsmStreamer::emitDirectiveSetFp( @@ -1133,7 +1157,7 @@ void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) { MCInst TmpInst; TmpInst.setOpcode(Mips::LUi); - TmpInst.addOperand(MCOperand::createReg(Mips::GP)); + TmpInst.addOperand(MCOperand::createReg(GPReg)); const MCExpr *HiSym = MipsMCExpr::create( MipsMCExpr::MEK_HI, MCSymbolRefExpr::create("_gp_disp", MCSymbolRefExpr::VK_None, @@ -1145,8 +1169,8 @@ void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) { TmpInst.clear(); TmpInst.setOpcode(Mips::ADDiu); - TmpInst.addOperand(MCOperand::createReg(Mips::GP)); - TmpInst.addOperand(MCOperand::createReg(Mips::GP)); + TmpInst.addOperand(MCOperand::createReg(GPReg)); + TmpInst.addOperand(MCOperand::createReg(GPReg)); const MCExpr *LoSym = MipsMCExpr::create( MipsMCExpr::MEK_LO, MCSymbolRefExpr::create("_gp_disp", MCSymbolRefExpr::VK_None, @@ -1158,14 +1182,19 @@ void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) { TmpInst.clear(); TmpInst.setOpcode(Mips::ADDu); - TmpInst.addOperand(MCOperand::createReg(Mips::GP)); - TmpInst.addOperand(MCOperand::createReg(Mips::GP)); + TmpInst.addOperand(MCOperand::createReg(GPReg)); + TmpInst.addOperand(MCOperand::createReg(GPReg)); TmpInst.addOperand(MCOperand::createReg(RegNo)); getStreamer().EmitInstruction(TmpInst, STI); forbidModuleDirective(); } +void MipsTargetELFStreamer::emitDirectiveCpLocal(unsigned RegNo) { + if (Pic) + MipsTargetStreamer::emitDirectiveCpLocal(RegNo); +} + bool MipsTargetELFStreamer::emitDirectiveCpRestore( int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc, const MCSubtargetInfo *STI) { @@ -1182,7 +1211,7 @@ bool MipsTargetELFStreamer::emitDirectiveCpRestore( return true; // Store the $gp on the stack. - emitStoreWithImmOffset(Mips::SW, Mips::GP, Mips::SP, Offset, GetATReg, IDLoc, + emitStoreWithImmOffset(Mips::SW, GPReg, Mips::SP, Offset, GetATReg, IDLoc, STI); return true; } @@ -1203,10 +1232,10 @@ void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo, // Either store the old $gp in a register or on the stack if (IsReg) { // move $save, $gpreg - emitRRR(Mips::OR64, RegOrOffset, Mips::GP, Mips::ZERO, SMLoc(), &STI); + emitRRR(Mips::OR64, RegOrOffset, GPReg, Mips::ZERO, SMLoc(), &STI); } else { // sd $gpreg, offset($sp) - emitRRI(Mips::SD, Mips::GP, Mips::SP, RegOrOffset, SMLoc(), &STI); + emitRRI(Mips::SD, GPReg, Mips::SP, RegOrOffset, SMLoc(), &STI); } if (getABI().IsN32()) { @@ -1219,11 +1248,11 @@ void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo, MCA.getContext()); // lui $gp, %hi(__gnu_local_gp) - emitRX(Mips::LUi, Mips::GP, MCOperand::createExpr(HiExpr), SMLoc(), &STI); + emitRX(Mips::LUi, GPReg, MCOperand::createExpr(HiExpr), SMLoc(), &STI); // addiu $gp, $gp, %lo(__gnu_local_gp) - emitRRX(Mips::ADDiu, Mips::GP, Mips::GP, MCOperand::createExpr(LoExpr), - SMLoc(), &STI); + emitRRX(Mips::ADDiu, GPReg, GPReg, MCOperand::createExpr(LoExpr), SMLoc(), + &STI); return; } @@ -1236,14 +1265,14 @@ void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo, MCA.getContext()); // lui $gp, %hi(%neg(%gp_rel(funcSym))) - emitRX(Mips::LUi, Mips::GP, MCOperand::createExpr(HiExpr), SMLoc(), &STI); + emitRX(Mips::LUi, GPReg, MCOperand::createExpr(HiExpr), SMLoc(), &STI); // addiu $gp, $gp, %lo(%neg(%gp_rel(funcSym))) - emitRRX(Mips::ADDiu, Mips::GP, Mips::GP, MCOperand::createExpr(LoExpr), - SMLoc(), &STI); + emitRRX(Mips::ADDiu, GPReg, GPReg, MCOperand::createExpr(LoExpr), SMLoc(), + &STI); // daddu $gp, $gp, $funcreg - emitRRR(Mips::DADDu, Mips::GP, Mips::GP, RegNo, SMLoc(), &STI); + emitRRR(Mips::DADDu, GPReg, GPReg, RegNo, SMLoc(), &STI); } void MipsTargetELFStreamer::emitDirectiveCpreturn(unsigned SaveLocation, @@ -1256,12 +1285,12 @@ void MipsTargetELFStreamer::emitDirectiveCpreturn(unsigned SaveLocation, // Either restore the old $gp from a register or on the stack if (SaveLocationIsRegister) { Inst.setOpcode(Mips::OR); - Inst.addOperand(MCOperand::createReg(Mips::GP)); + Inst.addOperand(MCOperand::createReg(GPReg)); Inst.addOperand(MCOperand::createReg(SaveLocation)); Inst.addOperand(MCOperand::createReg(Mips::ZERO)); } else { Inst.setOpcode(Mips::LD); - Inst.addOperand(MCOperand::createReg(Mips::GP)); + Inst.addOperand(MCOperand::createReg(GPReg)); Inst.addOperand(MCOperand::createReg(Mips::SP)); Inst.addOperand(MCOperand::createImm(SaveLocation)); } diff --git a/lib/Target/Mips/MicroMips32r6InstrFormats.td b/lib/Target/Mips/MicroMips32r6InstrFormats.td index ed5b8dd71a51..dbff0f6200f2 100644 --- a/lib/Target/Mips/MicroMips32r6InstrFormats.td +++ b/lib/Target/Mips/MicroMips32r6InstrFormats.td @@ -1,9 +1,8 @@ //=- MicroMips32r6InstrFormats.td - Mips32r6 Instruction Formats -*- tablegen -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/MicroMips32r6InstrInfo.td b/lib/Target/Mips/MicroMips32r6InstrInfo.td index 814918d25e70..425773dc57f1 100644 --- a/lib/Target/Mips/MicroMips32r6InstrInfo.td +++ b/lib/Target/Mips/MicroMips32r6InstrInfo.td @@ -1,9 +1,8 @@ //=- MicroMips32r6InstrInfo.td - MicroMips r6 Instruction Information -*- tablegen -*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -246,6 +245,7 @@ class MADDF_D_MMR6_ENC : POOL32F_ARITHF_FM_MMR6<"maddf.d", 1, 0b110111000>; class MSUBF_S_MMR6_ENC : POOL32F_ARITHF_FM_MMR6<"msubf.s", 0, 0b111111000>; class MSUBF_D_MMR6_ENC : POOL32F_ARITHF_FM_MMR6<"msubf.d", 1, 0b111111000>; class FMOV_S_MMR6_ENC : POOL32F_MOV_NEG_FM_MMR6<"mov.s", 0, 0b0000001>; +class FMOV_D_MMR6_ENC : POOL32F_MOV_NEG_FM_MMR6<"mov.d", 1, 0b0000001>; class FNEG_S_MMR6_ENC : POOL32F_MOV_NEG_FM_MMR6<"neg.s", 0, 0b0101101>; class MAX_S_MMR6_ENC : POOL32F_MINMAX_FM<"max.s", 0, 0b000001011>; class MAX_D_MMR6_ENC : POOL32F_MINMAX_FM<"max.d", 1, 0b000001011>; @@ -460,6 +460,7 @@ class JALRC16_MMR6_DESC_BASE<string opstr, RegisterOperand RO> let isCall = 1; let hasDelaySlot = 0; let Defs = [RA]; + let hasPostISelHook = 1; } class JALRC16_MMR6_DESC : JALRC16_MMR6_DESC_BASE<"jalr", GPR32Opnd>; @@ -889,6 +890,8 @@ class FMOV_FNEG_MMR6_DESC_BASE<string instr_asm, RegisterOperand DstRC, } class FMOV_S_MMR6_DESC : FMOV_FNEG_MMR6_DESC_BASE<"mov.s", FGR32Opnd, FGR32Opnd, II_MOV_S>; +class FMOV_D_MMR6_DESC + : FMOV_FNEG_MMR6_DESC_BASE<"mov.d", FGR64Opnd, FGR64Opnd, II_MOV_D>; class FNEG_S_MMR6_DESC : FMOV_FNEG_MMR6_DESC_BASE<"neg.s", FGR32Opnd, FGR32Opnd, II_NEG, fneg>; @@ -1039,7 +1042,7 @@ class TRUNC_L_D_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"trunc.l.d", FGR64Opnd, class TRUNC_W_S_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"trunc.w.s", FGR32Opnd, FGR32Opnd, II_TRUNC>; class TRUNC_W_D_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"trunc.w.d", FGR32Opnd, - AFGR64Opnd, II_TRUNC>; + FGR64Opnd, II_TRUNC>; class SQRT_S_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"sqrt.s", FGR32Opnd, FGR32Opnd, II_SQRT_S, fsqrt>; class SQRT_D_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"sqrt.d", AFGR64Opnd, AFGR64Opnd, @@ -1210,7 +1213,7 @@ class SW16_MMR6_DESC : SB16_MMR6_DESC_BASE<"sw16", GPRMM16OpndZero, GPRMM16Opnd, class SWSP_MMR6_DESC : MicroMipsInst16<(outs), (ins GPR32Opnd:$rt, mem_mm_sp_imm5_lsl2:$offset), !strconcat("sw", "\t$rt, $offset"), [], II_SW, FrmI>, - MMR6Arch<"sw"> { + MMR6Arch<"swsp"> { let DecoderMethod = "DecodeMemMMSPImm5Lsl2"; let mayStore = 1; } @@ -1461,6 +1464,8 @@ def MSUBF_D_MMR6 : R6MMR6Rel, MSUBF_D_MMR6_ENC, MSUBF_D_MMR6_DESC, ISA_MICROMIPS32R6; def FMOV_S_MMR6 : StdMMR6Rel, FMOV_S_MMR6_ENC, FMOV_S_MMR6_DESC, ISA_MICROMIPS32R6; +def FMOV_D_MMR6 : StdMMR6Rel, FMOV_D_MMR6_ENC, FMOV_D_MMR6_DESC, + ISA_MICROMIPS32R6; def FNEG_S_MMR6 : StdMMR6Rel, FNEG_S_MMR6_ENC, FNEG_S_MMR6_DESC, ISA_MICROMIPS32R6; def MAX_S_MMR6 : R6MMR6Rel, MAX_S_MMR6_ENC, MAX_S_MMR6_DESC, ISA_MICROMIPS32R6; @@ -1749,6 +1754,8 @@ def : MipsPat<(f32 fpimm0), (MTC1_MMR6 ZERO)>, ISA_MICROMIPS32R6; def : MipsPat<(f32 fpimm0neg), (FNEG_S_MMR6 (MTC1_MMR6 ZERO))>, ISA_MICROMIPS32R6; def : MipsPat<(MipsTruncIntFP FGR64Opnd:$src), (TRUNC_W_D_MMR6 FGR64Opnd:$src)>, ISA_MICROMIPS32R6; +def : MipsPat<(MipsTruncIntFP FGR32Opnd:$src), + (TRUNC_W_S_MMR6 FGR32Opnd:$src)>, ISA_MICROMIPS32R6; def : MipsPat<(and GPRMM16:$src, immZExtAndi16:$imm), (ANDI16_MMR6 GPRMM16:$src, immZExtAndi16:$imm)>, @@ -1767,6 +1774,19 @@ let AddedComplexity = 41 in { def : StoreRegImmPat<SDC1_D64_MMR6, f64>, FGR_64, ISA_MICROMIPS32R6; } +let isCall=1, hasDelaySlot=0, isCTI=1, Defs = [RA] in { + class JumpLinkMMR6<Instruction JumpInst, DAGOperand Opnd> : + PseudoSE<(outs), (ins calltarget:$target), [], II_JAL>, + PseudoInstExpansion<(JumpInst Opnd:$target)>; +} + +def JAL_MMR6 : JumpLinkMMR6<BALC_MMR6, brtarget26_mm>, ISA_MICROMIPS32R6; + +def : MipsPat<(MipsJmpLink (i32 texternalsym:$dst)), + (JAL_MMR6 texternalsym:$dst)>, ISA_MICROMIPS32R6; +def : MipsPat<(MipsJmpLink (iPTR tglobaladdr:$dst)), + (JAL_MMR6 tglobaladdr:$dst)>, ISA_MICROMIPS32R6; + def TAILCALL_MMR6 : TailCall<BC_MMR6, brtarget26_mm>, ISA_MICROMIPS32R6; def TAILCALLREG_MMR6 : TailCallReg<JRC16_MM, GPR32Opnd>, ISA_MICROMIPS32R6; diff --git a/lib/Target/Mips/MicroMipsDSPInstrFormats.td b/lib/Target/Mips/MicroMipsDSPInstrFormats.td index 0d444dfc9fad..26b6cf8994ca 100644 --- a/lib/Target/Mips/MicroMipsDSPInstrFormats.td +++ b/lib/Target/Mips/MicroMipsDSPInstrFormats.td @@ -1,9 +1,8 @@ //===-- MicroMipsDSPInstrFormats.td - Instruction Formats --*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MicroMipsDSPInstrInfo.td b/lib/Target/Mips/MicroMipsDSPInstrInfo.td index 132de6be750d..5a12568893af 100644 --- a/lib/Target/Mips/MicroMipsDSPInstrInfo.td +++ b/lib/Target/Mips/MicroMipsDSPInstrInfo.td @@ -1,9 +1,8 @@ //===- MicroMipsDSPInstrInfo.td - Micromips DSP instructions -*- tablegen *-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/MicroMipsInstrFPU.td b/lib/Target/Mips/MicroMipsInstrFPU.td index 1731afc1961f..5d87068ff407 100644 --- a/lib/Target/Mips/MicroMipsInstrFPU.td +++ b/lib/Target/Mips/MicroMipsInstrFPU.td @@ -1,9 +1,8 @@ //==- MicroMipsInstrFPU.td - microMIPS FPU Instruction Info -*- tablegen -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -114,8 +113,7 @@ multiclass ABSS_MMM<string opstr, InstrItinClass Itin, ISA_MICROMIPS, FGR_32 { string DecoderNamespace = "MicroMips"; } - // FIXME: This needs to be part of the instruction mapping tables. - def _D64_MM : ABSS_FT<opstr, FGR64Opnd, FGR64Opnd, Itin, OpNode>, + def _D64_MM : StdMMR6Rel, ABSS_FT<opstr, FGR64Opnd, FGR64Opnd, Itin, OpNode>, ISA_MICROMIPS, FGR_64 { string DecoderNamespace = "MicroMipsFP64"; } @@ -124,7 +122,7 @@ multiclass ABSS_MMM<string opstr, InstrItinClass Itin, defm FSQRT : ABSS_MMM<"sqrt.d", II_SQRT_D, fsqrt>, ROUND_W_FM_MM<1, 0x28>; defm FABS : ABSS_MMM<"abs.d", II_SQRT_D, fabs>, ABS_FM_MM<1, 0xd>; -let DecoderNamespace = "MicroMips" in { +let DecoderNamespace = "MicroMips", AdditionalPredicates = [UseAbs] in { def FABS_S_MM : MMRel, ABSS_FT<"abs.s", FGR32Opnd, FGR32Opnd, II_ABS, fabs>, ABS_FM_MM<0, 0xd>, ISA_MICROMIPS; } @@ -266,7 +264,7 @@ let DecoderNamespace = "MicroMips" in { ROUND_W_FM_MM<0b1, 0b01001000>, ISA_MICROMIPS, FGR_64; def RSQRT_S_MM : MMRel, ABSS_FT<"rsqrt.s", FGR32Opnd, FGR32Opnd, II_RECIP_S>, - ROUND_W_FM_MM<0b0, 0b00001000>; + ROUND_W_FM_MM<0b0, 0b00001000>, ISA_MICROMIPS; def RSQRT_D32_MM : MMRel, ABSS_FT<"rsqrt.d", AFGR64Opnd, AFGR64Opnd, II_RECIP_D>, ROUND_W_FM_MM<0b1, 0b00001000>, ISA_MICROMIPS, FGR_32 { @@ -425,6 +423,11 @@ def : MipsPat<(f64 (fpextend FGR32Opnd:$src)), def : MipsPat<(MipsTruncIntFP AFGR64Opnd:$src), (TRUNC_W_MM AFGR64Opnd:$src)>, ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; +def : MipsPat<(MipsTruncIntFP FGR64Opnd:$src), + (CVT_W_D64_MM FGR64Opnd:$src)>, ISA_MICROMIPS32_NOT_MIPS32R6, + FGR_64; +def : MipsPat<(MipsTruncIntFP FGR32Opnd:$src), + (TRUNC_W_S_MM FGR32Opnd:$src)>, ISA_MICROMIPS32_NOT_MIPS32R6; // Selects defm : MovzPats0<GPR32, FGR32, MOVZ_I_S_MM, SLT_MM, SLTu_MM, SLTi_MM, SLTiu_MM>, diff --git a/lib/Target/Mips/MicroMipsInstrFormats.td b/lib/Target/Mips/MicroMipsInstrFormats.td index 2a4cc279ef0d..e9fb9b310e3b 100644 --- a/lib/Target/Mips/MicroMipsInstrFormats.td +++ b/lib/Target/Mips/MicroMipsInstrFormats.td @@ -1,9 +1,8 @@ //===-- MicroMipsInstrFormats.td - microMIPS Inst Formats -*- tablegen -*--===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/MicroMipsInstrInfo.td b/lib/Target/Mips/MicroMipsInstrInfo.td index af380a0ec71e..9b7f7b25fa94 100644 --- a/lib/Target/Mips/MicroMipsInstrInfo.td +++ b/lib/Target/Mips/MicroMipsInstrInfo.td @@ -1,9 +1,8 @@ //===--- MicroMipsInstrFormats.td - microMIPS Inst Defs -*- tablegen -*----===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -426,6 +425,7 @@ class JumpLinkRegMM16<string opstr, RegisterOperand RO> : let isCall = 1; let hasDelaySlot = 1; let Defs = [RA]; + let hasPostISelHook = 1; } // 16-bit Jump Reg @@ -654,7 +654,7 @@ def LWGP_MM : LoadGPMM16<"lw", GPRMM16Opnd, II_LW, mem_mm_gp_simm7_lsl2>, LOAD_GP_FM_MM16<0x19>, ISA_MICROMIPS; def LWSP_MM : LoadSPMM16<"lw", GPR32Opnd, II_LW, mem_mm_sp_imm5_lsl2>, LOAD_STORE_SP_FM_MM16<0x12>, ISA_MICROMIPS; -def SWSP_MM : StoreSPMM16<"sw", GPR32Opnd, II_SW, mem_mm_sp_imm5_lsl2>, +def SWSP_MM : StoreSPMM16<"swsp", GPR32Opnd, II_SW, mem_mm_sp_imm5_lsl2>, LOAD_STORE_SP_FM_MM16<0x32>, ISA_MICROMIPS32_NOT_MIPS32R6; def ADDIUR1SP_MM : AddImmUR1SP<"addiur1sp", GPRMM16Opnd>, ADDIUR1SP_FM_MM16, ISA_MICROMIPS; @@ -694,6 +694,10 @@ def BREAK16_MM : BrkSdbbp16MM<"break16", II_BREAK>, BRKSDBBP16_FM_MM<0x28>, def SDBBP16_MM : BrkSdbbp16MM<"sdbbp16", II_SDBBP>, BRKSDBBP16_FM_MM<0x2C>, ISA_MICROMIPS32_NOT_MIPS32R6; +class WaitMM<string opstr> : + InstSE<(outs), (ins uimm10:$code_), !strconcat(opstr, "\t$code_"), [], + II_WAIT, FrmOther, opstr>; + let DecoderNamespace = "MicroMips" in { /// Load and Store Instructions - multiple def SWM16_MM : StoreMultMM16<"swm16", II_SWM>, LWM_FM_MM16<0x5>, @@ -706,13 +710,7 @@ let DecoderNamespace = "MicroMips" in { def CTC2_MM : InstSE<(outs COP2Opnd:$impl), (ins GPR32Opnd:$rt), "ctc2\t$rt, $impl", [], II_CTC2, FrmFR, "ctc2">, POOL32A_CFTC2_FM_MM<0b1101110100>, ISA_MICROMIPS; -} - -class WaitMM<string opstr> : - InstSE<(outs), (ins uimm10:$code_), !strconcat(opstr, "\t$code_"), [], - II_WAIT, FrmOther, opstr>; -let DecoderNamespace = "MicroMips" in { /// Compact Branch Instructions def BEQZC_MM : CompactBranchMM<"beqzc", brtarget_mm, seteq, GPR32Opnd>, COMPACT_BRANCH_FM_MM<0x7>, ISA_MICROMIPS32_NOT_MIPS32R6; @@ -822,8 +820,7 @@ let DecoderNamespace = "MicroMips" in { def SW_MM : Store<"sw", GPR32Opnd, null_frag, II_SW>, MMRel, LW_FM_MM<0x3e>, ISA_MICROMIPS; } -} -let DecoderNamespace = "MicroMips" in { + let DecoderMethod = "DecodeMemMMImm9" in { def LBE_MM : MMRel, Load<"lbe", GPR32Opnd, null_frag, II_LBE>, POOL32C_LHUE_FM_MM<0x18, 0x6, 0x4>, ISA_MICROMIPS, ASE_EVA; @@ -881,8 +878,7 @@ let DecoderNamespace = "MicroMips" in { def SWR_MM : MMRel, StoreLeftRightMM<"swr", MipsSWR, GPR32Opnd, mem_mm_12, II_SWR>, LWL_FM_MM<0x9>, ISA_MICROMIPS32_NOT_MIPS32R6; -} -let DecoderNamespace = "MicroMips" in { + /// Load and Store Instructions - multiple def SWM32_MM : StoreMultMM<"swm32", II_SWM>, LWM_FM_MM<0xd>, ISA_MICROMIPS; def LWM32_MM : LoadMultMM<"lwm32", II_LWM>, LWM_FM_MM<0x5>, ISA_MICROMIPS; @@ -1125,7 +1121,8 @@ let AdditionalPredicates = [NotDSP] in { ISA_MICROMIPS32_NOT_MIPS32R6; } -def TAILCALL_MM : TailCall<J_MM, jmptarget_mm>, ISA_MIPS1_NOT_32R6_64R6; +def TAILCALL_MM : TailCall<J_MM, jmptarget_mm>, + ISA_MICROMIPS32_NOT_MIPS32R6; def TAILCALLREG_MM : TailCallReg<JRC16_MM, GPR32Opnd>, ISA_MICROMIPS32_NOT_MIPS32R6; @@ -1139,9 +1136,7 @@ let DecoderNamespace = "MicroMips" in { def LWU_MM : MMRel, LoadMM<"lwu", GPR32Opnd, zextloadi32, II_LWU, mem_simm12>, LL_FM_MM<0xe>, ISA_MICROMIPS32_NOT_MIPS32R6; -} -let DecoderNamespace = "MicroMips" in { def MFGC0_MM : MMRel, MfCop0MM<"mfgc0", GPR32Opnd, COP0Opnd, II_MFGC0>, POOL32A_MFTC0_FM_MM<0b10011, 0b111100>, ISA_MICROMIPS32R5, ASE_VIRT; @@ -1204,7 +1199,7 @@ def : MipsPat<(atomic_load_32 addr:$a), (LW_MM addr:$a)>, ISA_MICROMIPS; def : MipsPat<(i32 immLi16:$imm), (LI16_MM immLi16:$imm)>, ISA_MICROMIPS; -defm : MaterializeImms<i32, ZERO, ADDiu_MM, LUi_MM, ORi_MM>, ISA_MICROMIPS; +defm : MaterializeImms<i32, ZERO, ADDiu_MM, LUi_MM, ORi_MM>, ISA_MICROMIPS; def : MipsPat<(not GPRMM16:$in), (NOT16_MM GPRMM16:$in)>, ISA_MICROMIPS; @@ -1453,3 +1448,6 @@ def : MipsInstAlias<"mtgc0 $rt, $rs", def : MipsInstAlias<"mthgc0 $rt, $rs", (MTHGC0_MM COP0Opnd:$rs, GPR32Opnd:$rt, 0), 0>, ISA_MICROMIPS32R5, ASE_VIRT; +def : MipsInstAlias<"sw $rt, $offset", + (SWSP_MM GPR32Opnd:$rt, mem_mm_sp_imm5_lsl2:$offset), 1>, + ISA_MICROMIPS; diff --git a/lib/Target/Mips/MicroMipsSizeReduction.cpp b/lib/Target/Mips/MicroMipsSizeReduction.cpp index f9062cc23da2..70af95592aa5 100644 --- a/lib/Target/Mips/MicroMipsSizeReduction.cpp +++ b/lib/Target/Mips/MicroMipsSizeReduction.cpp @@ -1,9 +1,8 @@ //=== MicroMipsSizeReduction.cpp - MicroMips size reduction pass --------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// ///\file diff --git a/lib/Target/Mips/Mips.h b/lib/Target/Mips/Mips.h index 6bb7aecc867a..b3faaab436f0 100644 --- a/lib/Target/Mips/Mips.h +++ b/lib/Target/Mips/Mips.h @@ -1,9 +1,8 @@ //===-- Mips.h - Top-level interface for Mips representation ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/Mips.td b/lib/Target/Mips/Mips.td index 2f3a1c399d3e..7b83ea8535ae 100644 --- a/lib/Target/Mips/Mips.td +++ b/lib/Target/Mips/Mips.td @@ -1,9 +1,8 @@ //===-- Mips.td - Describe the Mips Target Machine ---------*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // This is the top level entry point for the Mips target. @@ -83,6 +82,8 @@ def FeatureFPXX : SubtargetFeature<"fpxx", "IsFPXX", "true", "Support for FPXX">; def FeatureNaN2008 : SubtargetFeature<"nan2008", "IsNaN2008bit", "true", "IEEE 754-2008 NaN encoding">; +def FeatureAbs2008 : SubtargetFeature<"abs2008", "Abs2008", "true", + "Disable IEEE 754-2008 abs.fmt mode">; def FeatureSingleFloat : SubtargetFeature<"single-float", "IsSingleFloat", "true", "Only supports single precision float">; def FeatureSoftFloat : SubtargetFeature<"soft-float", "IsSoftFloat", "true", @@ -142,7 +143,7 @@ def FeatureMips32r6 : SubtargetFeature<"mips32r6", "MipsArchVersion", "Mips32r6", "Mips32r6 ISA Support [experimental]", [FeatureMips32r5, FeatureFP64Bit, - FeatureNaN2008]>; + FeatureNaN2008, FeatureAbs2008]>; def FeatureMips64 : SubtargetFeature<"mips64", "MipsArchVersion", "Mips64", "Mips64 ISA Support", [FeatureMips5, FeatureMips32]>; @@ -159,7 +160,7 @@ def FeatureMips64r6 : SubtargetFeature<"mips64r6", "MipsArchVersion", "Mips64r6", "Mips64r6 ISA Support [experimental]", [FeatureMips32r6, FeatureMips64r5, - FeatureNaN2008]>; + FeatureNaN2008, FeatureAbs2008]>; def FeatureSym32 : SubtargetFeature<"sym32", "HasSym32", "true", "Symbols are 32 bit on Mips64">; diff --git a/lib/Target/Mips/Mips16FrameLowering.cpp b/lib/Target/Mips/Mips16FrameLowering.cpp index 122c1f5377b6..5a2a916a6b7a 100644 --- a/lib/Target/Mips/Mips16FrameLowering.cpp +++ b/lib/Target/Mips/Mips16FrameLowering.cpp @@ -1,9 +1,8 @@ //===- Mips16FrameLowering.cpp - Mips16 Frame Information -----------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/Mips16FrameLowering.h b/lib/Target/Mips/Mips16FrameLowering.h index f7fa4dc3d86d..6b62453f8dfe 100644 --- a/lib/Target/Mips/Mips16FrameLowering.h +++ b/lib/Target/Mips/Mips16FrameLowering.h @@ -1,9 +1,8 @@ //===-- Mips16FrameLowering.h - Mips16 frame lowering ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/Mips16HardFloat.cpp b/lib/Target/Mips/Mips16HardFloat.cpp index f237bb6d4006..e9a3c7ec4b19 100644 --- a/lib/Target/Mips/Mips16HardFloat.cpp +++ b/lib/Target/Mips/Mips16HardFloat.cpp @@ -1,9 +1,8 @@ //===- Mips16HardFloat.cpp for Mips16 Hard Float --------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -415,7 +414,7 @@ static bool fixupFPReturnAndCall(Function &F, Module *M, Attribute::ReadNone); A = A.addAttribute(C, AttributeList::FunctionIndex, Attribute::NoInline); - Value *F = (M->getOrInsertFunction(Name, A, MyVoid, T)); + FunctionCallee 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(); diff --git a/lib/Target/Mips/Mips16HardFloatInfo.cpp b/lib/Target/Mips/Mips16HardFloatInfo.cpp index 2eb6e5ddd2d9..8a02e8156175 100644 --- a/lib/Target/Mips/Mips16HardFloatInfo.cpp +++ b/lib/Target/Mips/Mips16HardFloatInfo.cpp @@ -1,9 +1,8 @@ //===---- Mips16HardFloatInfo.cpp for Mips16 Hard Float -----===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/Mips16HardFloatInfo.h b/lib/Target/Mips/Mips16HardFloatInfo.h index 7295c287576d..b8c485b7e2e3 100644 --- a/lib/Target/Mips/Mips16HardFloatInfo.h +++ b/lib/Target/Mips/Mips16HardFloatInfo.h @@ -1,9 +1,8 @@ //===---- Mips16HardFloatInfo.h for Mips16 Hard Float --------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/Mips16ISelDAGToDAG.cpp b/lib/Target/Mips/Mips16ISelDAGToDAG.cpp index a0d5bd9ef305..3ab4f1e064da 100644 --- a/lib/Target/Mips/Mips16ISelDAGToDAG.cpp +++ b/lib/Target/Mips/Mips16ISelDAGToDAG.cpp @@ -1,9 +1,8 @@ //===-- Mips16ISelDAGToDAG.cpp - A Dag to Dag Inst Selector for Mips16 ----===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/Mips16ISelDAGToDAG.h b/lib/Target/Mips/Mips16ISelDAGToDAG.h index bbf8cc36f241..1ef194029f50 100644 --- a/lib/Target/Mips/Mips16ISelDAGToDAG.h +++ b/lib/Target/Mips/Mips16ISelDAGToDAG.h @@ -1,9 +1,8 @@ //===---- Mips16ISelDAGToDAG.h - A Dag to Dag Inst Selector for Mips ------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/Mips16ISelLowering.cpp b/lib/Target/Mips/Mips16ISelLowering.cpp index 79df622241a0..6d8e5aef2a3f 100644 --- a/lib/Target/Mips/Mips16ISelLowering.cpp +++ b/lib/Target/Mips/Mips16ISelLowering.cpp @@ -1,9 +1,8 @@ //===-- Mips16ISelLowering.h - Mips16 DAG Lowering Interface ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -156,11 +155,8 @@ llvm::createMips16TargetLowering(const MipsTargetMachine &TM, return new Mips16TargetLowering(TM, STI); } -bool -Mips16TargetLowering::allowsMisalignedMemoryAccesses(EVT VT, - unsigned, - unsigned, - bool *Fast) const { +bool Mips16TargetLowering::allowsMisalignedMemoryAccesses( + EVT VT, unsigned, unsigned, MachineMemOperand::Flags, bool *Fast) const { return false; } @@ -463,8 +459,7 @@ getOpndList(SmallVectorImpl<SDValue> &Ops, } // one more look at list of intrinsics const Mips16IntrinsicHelperType *Helper = - std::lower_bound(std::begin(Mips16IntrinsicHelper), - std::end(Mips16IntrinsicHelper), IntrinsicFind); + llvm::lower_bound(Mips16IntrinsicHelper, IntrinsicFind); if (Helper != std::end(Mips16IntrinsicHelper) && *Helper == IntrinsicFind) { Mips16HelperFunction = Helper->Helper; diff --git a/lib/Target/Mips/Mips16ISelLowering.h b/lib/Target/Mips/Mips16ISelLowering.h index 0ee0b816ef70..200249933577 100644 --- a/lib/Target/Mips/Mips16ISelLowering.h +++ b/lib/Target/Mips/Mips16ISelLowering.h @@ -1,9 +1,8 @@ //===-- Mips16ISelLowering.h - Mips16 DAG Lowering Interface ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -24,6 +23,7 @@ namespace llvm { bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace, unsigned Align, + MachineMemOperand::Flags Flags, bool *Fast) const override; MachineBasicBlock * diff --git a/lib/Target/Mips/Mips16InstrFormats.td b/lib/Target/Mips/Mips16InstrFormats.td index 4ff68bef957e..f4ac160c2ba5 100644 --- a/lib/Target/Mips/Mips16InstrFormats.td +++ b/lib/Target/Mips/Mips16InstrFormats.td @@ -1,9 +1,8 @@ //===- Mips16InstrFormats.td - Mips Instruction Formats ----*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/Mips16InstrInfo.cpp b/lib/Target/Mips/Mips16InstrInfo.cpp index efebc99b5dae..c234c309d760 100644 --- a/lib/Target/Mips/Mips16InstrInfo.cpp +++ b/lib/Target/Mips/Mips16InstrInfo.cpp @@ -1,9 +1,8 @@ //===- Mips16InstrInfo.cpp - Mips16 Instruction Information ---------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/Mips16InstrInfo.h b/lib/Target/Mips/Mips16InstrInfo.h index 6a802e4cce5d..dadcaa3055b3 100644 --- a/lib/Target/Mips/Mips16InstrInfo.h +++ b/lib/Target/Mips/Mips16InstrInfo.h @@ -1,9 +1,8 @@ //===- Mips16InstrInfo.h - Mips16 Instruction Information -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/Mips16InstrInfo.td b/lib/Target/Mips/Mips16InstrInfo.td index b7a1b9ce41bf..36b6c73d1008 100644 --- a/lib/Target/Mips/Mips16InstrInfo.td +++ b/lib/Target/Mips/Mips16InstrInfo.td @@ -1,9 +1,8 @@ //===- Mips16InstrInfo.td - Target Description for Mips16 -*- tablegen -*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -484,13 +483,11 @@ class SelT<string op1, string op2>: // // 32 bit constant // -def Constant32: - MipsPseudo16<(outs), (ins simm32:$imm), "\t.word $imm", []>; +def Constant32 : MipsPseudo16<(outs), (ins simm32:$imm), "\t.word $imm", []>; -def LwConstant32: +def LwConstant32 : MipsPseudo16<(outs CPU16Regs:$rx), (ins simm32:$imm, simm32:$constid), - "lw\t$rx, 1f\n\tb\t2f\n\t.align\t2\n1: \t.word\t$imm\n2:", []>; - + "lw\t$rx, 1f\n\tb\t2f\n\t.align\t2\n1: \t.word\t$imm\n2:", []>; // // Some general instruction class info diff --git a/lib/Target/Mips/Mips16RegisterInfo.cpp b/lib/Target/Mips/Mips16RegisterInfo.cpp index 751afd5ed369..5703f585a6a2 100644 --- a/lib/Target/Mips/Mips16RegisterInfo.cpp +++ b/lib/Target/Mips/Mips16RegisterInfo.cpp @@ -1,9 +1,8 @@ //===-- Mips16RegisterInfo.cpp - MIPS16 Register Information --------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/Mips16RegisterInfo.h b/lib/Target/Mips/Mips16RegisterInfo.h index d67a79b64033..fca78b43f96b 100644 --- a/lib/Target/Mips/Mips16RegisterInfo.h +++ b/lib/Target/Mips/Mips16RegisterInfo.h @@ -1,9 +1,8 @@ //===-- Mips16RegisterInfo.h - Mips16 Register Information ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/Mips32r6InstrFormats.td b/lib/Target/Mips/Mips32r6InstrFormats.td index 623af570a5e6..ccb6d1df777a 100644 --- a/lib/Target/Mips/Mips32r6InstrFormats.td +++ b/lib/Target/Mips/Mips32r6InstrFormats.td @@ -1,9 +1,8 @@ //=- Mips32r6InstrFormats.td - Mips32r6 Instruction Formats -*- tablegen -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/Mips32r6InstrInfo.td b/lib/Target/Mips/Mips32r6InstrInfo.td index 2bd0cf2d59a6..2c3048411a5c 100644 --- a/lib/Target/Mips/Mips32r6InstrInfo.td +++ b/lib/Target/Mips/Mips32r6InstrInfo.td @@ -1,9 +1,8 @@ //=- Mips32r6InstrInfo.td - Mips32r6 Instruction Information -*- tablegen -*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -150,7 +149,6 @@ class SELEQZ_ENC : SPECIAL_3R_FM<0b00000, 0b110101>; class SELNEZ_ENC : SPECIAL_3R_FM<0b00000, 0b110111>; class LWPC_ENC : PCREL19_FM<OPCODE2_LWPC>; -class LWUPC_ENC : PCREL19_FM<OPCODE2_LWUPC>; class MAX_S_ENC : COP1_3R_FM<0b011101, FIELD_FMT_S>; class MAX_D_ENC : COP1_3R_FM<0b011101, FIELD_FMT_D>; @@ -326,7 +324,6 @@ class PCREL_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, class ADDIUPC_DESC : PCREL_DESC_BASE<"addiupc", GPR32Opnd, simm19_lsl2, II_ADDIUPC>; class LWPC_DESC: PCREL_DESC_BASE<"lwpc", GPR32Opnd, simm19_lsl2, II_LWPC>; -class LWUPC_DESC: PCREL_DESC_BASE<"lwupc", GPR32Opnd, simm19_lsl2, II_LWUPC>; class ALIGN_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, Operand ImmOpnd, InstrItinClass itin> @@ -927,7 +924,6 @@ let AdditionalPredicates = [NotInMicroMips] in { } def LWPC : R6MMR6Rel, LWPC_ENC, LWPC_DESC, ISA_MIPS32R6; let AdditionalPredicates = [NotInMicroMips] in { - def LWUPC : R6MMR6Rel, LWUPC_ENC, LWUPC_DESC, ISA_MIPS32R6; def MADDF_S : MADDF_S_ENC, MADDF_S_DESC, ISA_MIPS32R6, HARDFLOAT; def MADDF_D : MADDF_D_ENC, MADDF_D_DESC, ISA_MIPS32R6, HARDFLOAT; def MAXA_D : MAXA_D_ENC, MAXA_D_DESC, ISA_MIPS32R6, HARDFLOAT; @@ -1105,7 +1101,7 @@ def : MipsPat<(select i32:$cond, immz, i32:$f), // Pseudo instructions let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, hasDelaySlot = 1, - hasExtraSrcRegAllocReq = 1, isCTI = 1, Defs = [AT] in { + hasExtraSrcRegAllocReq = 1, isCTI = 1, Defs = [AT], hasPostISelHook = 1 in { class TailCallRegR6<Instruction JumpInst, Register RT, RegisterOperand RO> : PseudoSE<(outs), (ins RO:$rs), [(MipsTailCall RO:$rs)], II_JR>, PseudoInstExpansion<(JumpInst RT:$rt, RO:$rs)>; diff --git a/lib/Target/Mips/Mips64InstrInfo.td b/lib/Target/Mips/Mips64InstrInfo.td index 5729182deafb..7f35280f7936 100644 --- a/lib/Target/Mips/Mips64InstrInfo.td +++ b/lib/Target/Mips/Mips64InstrInfo.td @@ -1,9 +1,8 @@ //===- Mips64InstrInfo.td - Mips64 Instruction Information -*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -250,7 +249,7 @@ def SC64 : SCBase<"sc", GPR32Opnd>, LW_FM<0x38>, PTR_64, def JR64 : IndirectBranch<"jr", GPR64Opnd>, MTLO_FM<8>, PTR_64; } -def JALR64 : JumpLinkReg<"jalr", GPR64Opnd>, JALR_FM; +def JALR64 : JumpLinkReg<"jalr", GPR64Opnd>, JALR_FM, PTR_64; /// Jump and Branch Instructions let isCodeGenOnly = 1 in { @@ -267,14 +266,15 @@ let isCodeGenOnly = 1 in { def BLTZ64 : CBranchZero<"bltz", brtarget, setlt, GPR64Opnd>, BGEZ_FM<1, 0>, GPR_64; let AdditionalPredicates = [NoIndirectJumpGuards] in - def JALR64Pseudo : JumpLinkRegPseudo<GPR64Opnd, JALR, RA, GPR32Opnd>; + def JALR64Pseudo : JumpLinkRegPseudo<GPR64Opnd, JALR, RA, GPR32Opnd>, + PTR_64; } let AdditionalPredicates = [NotInMicroMips], DecoderNamespace = "Mips64" in { - def JR_HB64 : JR_HB_DESC<GPR64Opnd>, JR_HB_ENC, ISA_MIPS32_NOT_32R6_64R6; - def JALR_HB64 : JALR_HB_DESC<GPR64Opnd>, JALR_HB_ENC, ISA_MIPS32R2; + def JR_HB64 : JR_HB_DESC<GPR64Opnd>, JR_HB_ENC, ISA_MIPS64_NOT_64R6; + def JALR_HB64 : JALR_HB_DESC<GPR64Opnd>, JALR_HB_ENC, ISA_MIPS64R2; } -def PseudoReturn64 : PseudoReturnBase<GPR64Opnd>; +def PseudoReturn64 : PseudoReturnBase<GPR64Opnd>, GPR_64; let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips, NoIndirectJumpGuards] in { @@ -290,7 +290,7 @@ let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips, ISA_MIPS32R2_NOT_32R6_64R6, PTR_64; def PseudoIndirectHazardBranch64 : PseudoIndirectBranchBase<JR_HB64, GPR64Opnd>, - ISA_MIPS32R2_NOT_32R6_64R6; + ISA_MIPS32R2_NOT_32R6_64R6, PTR_64; } /// Multiply and Divide Instructions. @@ -332,17 +332,17 @@ def PseudoMTLOHI64 : PseudoMTLOHI<ACC128, GPR64>, ISA_MIPS3_NOT_32R6_64R6; /// Sign Ext In Register Instructions. def SEB64 : SignExtInReg<"seb", i8, GPR64Opnd, II_SEB>, SEB_FM<0x10, 0x20>, - ISA_MIPS32R2; + ISA_MIPS32R2, GPR_64; def SEH64 : SignExtInReg<"seh", i16, GPR64Opnd, II_SEH>, SEB_FM<0x18, 0x20>, - ISA_MIPS32R2; + ISA_MIPS32R2, GPR_64; } /// Count Leading let AdditionalPredicates = [NotInMicroMips] in { def DCLZ : CountLeading0<"dclz", GPR64Opnd, II_DCLZ>, CLO_FM<0x24>, - ISA_MIPS64_NOT_64R6; + ISA_MIPS64_NOT_64R6, GPR_64; def DCLO : CountLeading1<"dclo", GPR64Opnd, II_DCLO>, CLO_FM<0x25>, - ISA_MIPS64_NOT_64R6; + ISA_MIPS64_NOT_64R6, GPR_64; /// Double Word Swap Bytes/HalfWords def DSBH : SubwordSwap<"dsbh", GPR64Opnd, II_DSBH>, SEB_FM<2, 0x24>, @@ -417,17 +417,25 @@ let isCodeGenOnly = 1, rs = 0, shamt = 0 in { // explanation. // Expands to: lui $dst, %highest/%higher/%hi/%lo($tgt) -def LONG_BRANCH_LUi2Op_64 : PseudoSE<(outs GPR64Opnd:$dst), - (ins brtarget:$tgt), []>, GPR_64; +def LONG_BRANCH_LUi2Op_64 : + PseudoSE<(outs GPR64Opnd:$dst), (ins brtarget:$tgt), []>, GPR_64 { + bit hasNoSchedulingInfo = 1; +} // Expands to: addiu $dst, %highest/%higher/%hi/%lo($tgt) -def LONG_BRANCH_DADDiu2Op : PseudoSE<(outs GPR64Opnd:$dst), - (ins GPR64Opnd:$src, brtarget:$tgt), []>, GPR_64; - +def LONG_BRANCH_DADDiu2Op : + PseudoSE<(outs GPR64Opnd:$dst), (ins GPR64Opnd:$src, brtarget:$tgt), []>, + GPR_64 { + bit hasNoSchedulingInfo = 1; +} // Expands to: daddiu $dst, $src, %PART($tgt - $baltgt) // where %PART may be %hi or %lo, depending on the relocation kind // that $tgt is annotated with. -def LONG_BRANCH_DADDiu : PseudoSE<(outs GPR64Opnd:$dst), - (ins GPR64Opnd:$src, brtarget:$tgt, brtarget:$baltgt), []>, GPR_64; +def LONG_BRANCH_DADDiu : + PseudoSE<(outs GPR64Opnd:$dst), + (ins GPR64Opnd:$src, brtarget:$tgt, brtarget:$baltgt), []>, + GPR_64 { + bit hasNoSchedulingInfo = 1; +} // Cavium Octeon cnMIPS instructions let DecoderNamespace = "CnMips", @@ -580,15 +588,15 @@ def DMTC2_OCTEON : MFC2OP<"dmtc2", GPR64Opnd, II_DMTC2>, MFC2OP_FM<0x12, 5>, } /// Move between CPU and coprocessor registers -let DecoderNamespace = "Mips64", Predicates = [HasMips64] in { +let DecoderNamespace = "Mips64" in { def DMFC0 : MFC3OP<"dmfc0", GPR64Opnd, COP0Opnd, II_DMFC0>, - MFC3OP_FM<0x10, 1, 0>, ISA_MIPS3; + MFC3OP_FM<0x10, 1, 0>, ISA_MIPS3, GPR_64; def DMTC0 : MTC3OP<"dmtc0", COP0Opnd, GPR64Opnd, II_DMTC0>, - MFC3OP_FM<0x10, 5, 0>, ISA_MIPS3; + MFC3OP_FM<0x10, 5, 0>, ISA_MIPS3, GPR_64; def DMFC2 : MFC3OP<"dmfc2", GPR64Opnd, COP2Opnd, II_DMFC2>, - MFC3OP_FM<0x12, 1, 0>, ISA_MIPS3; + MFC3OP_FM<0x12, 1, 0>, ISA_MIPS3, GPR_64; def DMTC2 : MTC3OP<"dmtc2", COP2Opnd, GPR64Opnd, II_DMTC2>, - MFC3OP_FM<0x12, 5, 0>, ISA_MIPS3; + MFC3OP_FM<0x12, 5, 0>, ISA_MIPS3, GPR_64; } /// Move between CPU and guest coprocessor registers (Virtualization ASE) @@ -600,7 +608,7 @@ let DecoderNamespace = "Mips64" in { } let AdditionalPredicates = [UseIndirectJumpsHazard] in - def JALRHB64Pseudo : JumpLinkRegPseudo<GPR64Opnd, JALR_HB64, RA_64>; + def JALRHB64Pseudo : JumpLinkRegPseudo<GPR64Opnd, JALR_HB64, RA_64>, PTR_64; //===----------------------------------------------------------------------===// // Arbitrary patterns that map to one or more instructions @@ -845,7 +853,7 @@ def : MipsPat<(i64 (sext (i32 (sub GPR32:$src, GPR32:$src2)))), (SUBu GPR32:$src, GPR32:$src2), sub_32)>; def : MipsPat<(i64 (sext (i32 (mul GPR32:$src, GPR32:$src2)))), (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - (MUL GPR32:$src, GPR32:$src2), sub_32)>, ISA_MIPS3_NOT_32R6_64R6; + (MUL GPR32:$src, GPR32:$src2), sub_32)>, ISA_MIPS32_NOT_32R6_64R6; def : MipsPat<(i64 (sext (i32 (MipsMFHI ACC64:$src)))), (INSERT_SUBREG (i64 (IMPLICIT_DEF)), (PseudoMFHI ACC64:$src), sub_32)>; @@ -1147,5 +1155,33 @@ def SLTUImm64 : MipsAsmPseudoInst<(outs GPR64Opnd:$rs), def : MipsInstAlias<"sltu\t$rs, $imm", (SLTUImm64 GPR64Opnd:$rs, GPR64Opnd:$rs, imm64:$imm)>, GPR_64; +def SGEImm64 : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), + (ins GPR64Opnd:$rs, imm64:$imm), + "sge\t$rd, $rs, $imm">, GPR_64; +def : MipsInstAlias<"sge $rs, $imm", (SGEImm64 GPR64Opnd:$rs, + GPR64Opnd:$rs, + imm64:$imm), 0>, GPR_64; + +def SGEUImm64 : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), + (ins GPR64Opnd:$rs, imm64:$imm), + "sgeu\t$rd, $rs, $imm">, GPR_64; +def : MipsInstAlias<"sgeu $rs, $imm", (SGEUImm64 GPR64Opnd:$rs, + GPR64Opnd:$rs, + imm64:$imm), 0>, GPR_64; + +def SGTImm64 : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), + (ins GPR64Opnd:$rs, imm64:$imm), + "sgt\t$rd, $rs, $imm">, GPR_64; +def : MipsInstAlias<"sgt $rs, $imm", (SGTImm64 GPR64Opnd:$rs, + GPR64Opnd:$rs, + imm64:$imm), 0>, GPR_64; + +def SGTUImm64 : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), + (ins GPR64Opnd:$rs, imm64:$imm), + "sgtu\t$rd, $rs, $imm">, GPR_64; +def : MipsInstAlias<"sgtu $rs, $imm", (SGTUImm64 GPR64Opnd:$rs, + GPR64Opnd:$rs, + imm64:$imm), 0>, GPR_64; + def : MipsInstAlias<"rdhwr $rt, $rs", (RDHWR64 GPR64Opnd:$rt, HWRegsOpnd:$rs, 0), 1>, GPR_64; diff --git a/lib/Target/Mips/Mips64r6InstrInfo.td b/lib/Target/Mips/Mips64r6InstrInfo.td index ac223bc77256..d746bb61f824 100644 --- a/lib/Target/Mips/Mips64r6InstrInfo.td +++ b/lib/Target/Mips/Mips64r6InstrInfo.td @@ -1,9 +1,8 @@ //=- Mips64r6InstrInfo.td - Mips64r6 Instruction Information -*- tablegen -*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -37,6 +36,7 @@ class DMUHU_ENC : SPECIAL_3R_FM<0b00011, 0b011101>; class DMUL_R6_ENC : SPECIAL_3R_FM<0b00010, 0b011100>; class DMULU_ENC : SPECIAL_3R_FM<0b00010, 0b011101>; class LDPC_ENC : PCREL18_FM<OPCODE3_LDPC>; +class LWUPC_ENC : PCREL19_FM<OPCODE2_LWUPC>; class LLD_R6_ENC : SPECIAL3_LL_SC_FM<OPCODE6_LLD>; class SCD_R6_ENC : SPECIAL3_LL_SC_FM<OPCODE6_SCD>; class CRC32D_ENC : SPECIAL3_2R_SZ_CRC<3,0>; @@ -73,6 +73,7 @@ class DMUHU_DESC : MUL_R6_DESC_BASE<"dmuhu", GPR64Opnd, II_DMUHU, mulhu>; class DMUL_R6_DESC : MUL_R6_DESC_BASE<"dmul", GPR64Opnd, II_DMUL, mul>; class DMULU_DESC : MUL_R6_DESC_BASE<"dmulu", GPR64Opnd, II_DMUL>; class LDPC_DESC : PCREL_DESC_BASE<"ldpc", GPR64Opnd, simm18_lsl3, II_LDPC>; +class LWUPC_DESC : PCREL_DESC_BASE<"lwupc", GPR32Opnd, simm19_lsl2, II_LWUPC>; class LLD_R6_DESC : LL_R6_DESC_BASE<"lld", GPR64Opnd, mem_simmptr, II_LLD>; class SCD_R6_DESC : SC_R6_DESC_BASE<"scd", GPR64Opnd, II_SCD>; class SELEQZ64_DESC : SELEQNE_Z_DESC_BASE<"seleqz", GPR64Opnd>; @@ -148,6 +149,7 @@ let AdditionalPredicates = [NotInMicroMips] in { def LLD_R6 : LLD_R6_ENC, LLD_R6_DESC, ISA_MIPS64R6; } def LDPC: LDPC_ENC, LDPC_DESC, ISA_MIPS64R6; +def LWUPC : LWUPC_ENC, LWUPC_DESC, ISA_MIPS64R6; def SCD_R6 : SCD_R6_ENC, SCD_R6_DESC, ISA_MIPS32R6; let DecoderNamespace = "Mips32r6_64r6_GP64" in { def SELEQZ64 : SELEQZ_ENC, SELEQZ64_DESC, ISA_MIPS32R6, GPR_64; diff --git a/lib/Target/Mips/MipsAnalyzeImmediate.cpp b/lib/Target/Mips/MipsAnalyzeImmediate.cpp index 4e17ee327ab6..ae2b83c414db 100644 --- a/lib/Target/Mips/MipsAnalyzeImmediate.cpp +++ b/lib/Target/Mips/MipsAnalyzeImmediate.cpp @@ -1,9 +1,8 @@ //===- MipsAnalyzeImmediate.cpp - Analyze Immediates ----------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MipsAnalyzeImmediate.h b/lib/Target/Mips/MipsAnalyzeImmediate.h index 1c520242fb8d..018b9d824526 100644 --- a/lib/Target/Mips/MipsAnalyzeImmediate.h +++ b/lib/Target/Mips/MipsAnalyzeImmediate.h @@ -1,9 +1,8 @@ //===- MipsAnalyzeImmediate.h - Analyze Immediates -------------*- C++ -*--===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp index 362431fd42a6..db83fe49cec0 100644 --- a/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/MipsAsmPrinter.cpp @@ -1,9 +1,8 @@ //===- MipsAsmPrinter.cpp - Mips LLVM Assembly Printer --------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -13,9 +12,9 @@ //===----------------------------------------------------------------------===// #include "MipsAsmPrinter.h" -#include "InstPrinter/MipsInstPrinter.h" #include "MCTargetDesc/MipsABIInfo.h" #include "MCTargetDesc/MipsBaseInfo.h" +#include "MCTargetDesc/MipsInstPrinter.h" #include "MCTargetDesc/MipsMCNaCl.h" #include "MCTargetDesc/MipsMCTargetDesc.h" #include "Mips.h" @@ -24,6 +23,7 @@ #include "MipsSubtarget.h" #include "MipsTargetMachine.h" #include "MipsTargetStreamer.h" +#include "TargetInfo/MipsTargetInfo.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" @@ -68,6 +68,8 @@ using namespace llvm; #define DEBUG_TYPE "mips-asm-printer" +extern cl::opt<bool> EmitJalrReloc; + MipsTargetStreamer &MipsAsmPrinter::getTargetStreamer() const { return static_cast<MipsTargetStreamer &>(*OutStreamer->getTargetStreamer()); } @@ -148,6 +150,40 @@ void MipsAsmPrinter::emitPseudoIndirectBranch(MCStreamer &OutStreamer, EmitToStreamer(OutStreamer, TmpInst0); } +// If there is an MO_JALR operand, insert: +// +// .reloc tmplabel, R_{MICRO}MIPS_JALR, symbol +// tmplabel: +// +// This is an optimization hint for the linker which may then replace +// an indirect call with a direct branch. +static void emitDirectiveRelocJalr(const MachineInstr &MI, + MCContext &OutContext, + TargetMachine &TM, + MCStreamer &OutStreamer, + const MipsSubtarget &Subtarget) { + for (unsigned int I = MI.getDesc().getNumOperands(), E = MI.getNumOperands(); + I < E; ++I) { + MachineOperand MO = MI.getOperand(I); + if (MO.isMCSymbol() && (MO.getTargetFlags() & MipsII::MO_JALR)) { + MCSymbol *Callee = MO.getMCSymbol(); + if (Callee && !Callee->getName().empty()) { + MCSymbol *OffsetLabel = OutContext.createTempSymbol(); + const MCExpr *OffsetExpr = + MCSymbolRefExpr::create(OffsetLabel, OutContext); + const MCExpr *CaleeExpr = + MCSymbolRefExpr::create(Callee, OutContext); + OutStreamer.EmitRelocDirective + (*OffsetExpr, + Subtarget.inMicroMipsMode() ? "R_MICROMIPS_JALR" : "R_MIPS_JALR", + CaleeExpr, SMLoc(), *TM.getMCSubtargetInfo()); + OutStreamer.EmitLabel(OffsetLabel); + return; + } + } + } +} + void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { MipsTargetStreamer &TS = getTargetStreamer(); unsigned Opc = MI->getOpcode(); @@ -207,6 +243,11 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { return; } + if (EmitJalrReloc && + (MI->isReturn() || MI->isCall() || MI->isIndirectBranch())) { + emitDirectiveRelocJalr(*MI, OutContext, TM, *OutStreamer, *Subtarget); + } + MachineBasicBlock::const_instr_iterator I = MI->getIterator(); MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); @@ -470,8 +511,7 @@ bool MipsAsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock* // Print out an operand for an inline asm expression. bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, - unsigned AsmVariant, const char *ExtraCode, - raw_ostream &O) { + const char *ExtraCode, raw_ostream &O) { // Does this asm operand have a single letter operand modifier? if (ExtraCode && ExtraCode[0]) { if (ExtraCode[1] != 0) return true; // Unknown modifier. @@ -480,7 +520,7 @@ bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, switch (ExtraCode[0]) { default: // See if this is a generic print operand - return AsmPrinter::PrintAsmOperand(MI,OpNum,AsmVariant,ExtraCode,O); + return AsmPrinter::PrintAsmOperand(MI, OpNum, ExtraCode, O); case 'X': // hex const int if ((MO.getType()) != MachineOperand::MO_Immediate) return true; @@ -576,7 +616,7 @@ bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, } bool MipsAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, - unsigned OpNum, unsigned AsmVariant, + unsigned OpNum, const char *ExtraCode, raw_ostream &O) { assert(OpNum + 1 < MI->getNumOperands() && "Insufficient operands"); @@ -653,7 +693,7 @@ void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, return; case MachineOperand::MO_GlobalAddress: - getSymbol(MO.getGlobal())->print(O, MAI); + PrintSymbolOperand(MO, O); break; case MachineOperand::MO_BlockAddress: { @@ -772,7 +812,8 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { // We should always emit a '.module fp=...' but binutils 2.24 does not accept // it. We therefore emit it when it contradicts the ABI defaults (-mfpxx or // -mfp64) and omit it otherwise. - if (ABI.IsO32() && (STI.isABI_FPXX() || STI.isFP64bit())) + if ((ABI.IsO32() && (STI.isABI_FPXX() || STI.isFP64bit())) || + STI.useSoftFloat()) TS.emitDirectiveModuleFP(); // We should always emit a '.module [no]oddspreg' but binutils 2.24 does not diff --git a/lib/Target/Mips/MipsAsmPrinter.h b/lib/Target/Mips/MipsAsmPrinter.h index eb58234e3e77..173a1312812e 100644 --- a/lib/Target/Mips/MipsAsmPrinter.h +++ b/lib/Target/Mips/MipsAsmPrinter.h @@ -1,9 +1,8 @@ //===- MipsAsmPrinter.h - Mips LLVM Assembly Printer -----------*- C++ -*--===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -146,11 +145,9 @@ public: bool isBlockOnlyReachableByFallthrough( const MachineBasicBlock* MBB) const override; bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode, - raw_ostream &O) override; + const char *ExtraCode, raw_ostream &O) override; bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, - unsigned AsmVariant, const char *ExtraCode, - raw_ostream &O) override; + const char *ExtraCode, raw_ostream &O) override; void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O); void printMemOperandEA(const MachineInstr *MI, int opNum, raw_ostream &O); diff --git a/lib/Target/Mips/MipsBranchExpansion.cpp b/lib/Target/Mips/MipsBranchExpansion.cpp index e59267c4fd9b..1523a6c020aa 100644 --- a/lib/Target/Mips/MipsBranchExpansion.cpp +++ b/lib/Target/Mips/MipsBranchExpansion.cpp @@ -1,9 +1,8 @@ //===----------------------- MipsBranchExpansion.cpp ----------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// \file diff --git a/lib/Target/Mips/MipsCCState.cpp b/lib/Target/Mips/MipsCCState.cpp index 90cb3f437bd5..ef48c850a1b8 100644 --- a/lib/Target/Mips/MipsCCState.cpp +++ b/lib/Target/Mips/MipsCCState.cpp @@ -1,9 +1,8 @@ //===---- MipsCCState.cpp - CCState with Mips specific extensions ---------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MipsCCState.h b/lib/Target/Mips/MipsCCState.h index 27901699480b..fd2fd97c8f13 100644 --- a/lib/Target/Mips/MipsCCState.h +++ b/lib/Target/Mips/MipsCCState.h @@ -1,9 +1,8 @@ //===---- MipsCCState.h - CCState with Mips specific extensions -----------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MipsCallLowering.cpp b/lib/Target/Mips/MipsCallLowering.cpp index c550fadf6632..da65689ecff5 100644 --- a/lib/Target/Mips/MipsCallLowering.cpp +++ b/lib/Target/Mips/MipsCallLowering.cpp @@ -1,9 +1,8 @@ //===- MipsCallLowering.cpp -------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -15,6 +14,7 @@ #include "MipsCallLowering.h" #include "MipsCCState.h" +#include "MipsMachineFunction.h" #include "MipsTargetMachine.h" #include "llvm/CodeGen/Analysis.h" #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" @@ -24,10 +24,10 @@ using namespace llvm; MipsCallLowering::MipsCallLowering(const MipsTargetLowering &TLI) : CallLowering(&TLI) {} -bool MipsCallLowering::MipsHandler::assign(unsigned VReg, - const CCValAssign &VA) { +bool MipsCallLowering::MipsHandler::assign(Register VReg, const CCValAssign &VA, + const EVT &VT) { if (VA.isRegLoc()) { - assignValueToReg(VReg, VA); + assignValueToReg(VReg, VA, VT); } else if (VA.isMemLoc()) { assignValueToAddress(VReg, VA); } else { @@ -36,24 +36,25 @@ bool MipsCallLowering::MipsHandler::assign(unsigned VReg, return true; } -bool MipsCallLowering::MipsHandler::assignVRegs(ArrayRef<unsigned> VRegs, +bool MipsCallLowering::MipsHandler::assignVRegs(ArrayRef<Register> VRegs, ArrayRef<CCValAssign> ArgLocs, - unsigned ArgLocsStartIndex) { + unsigned ArgLocsStartIndex, + const EVT &VT) { for (unsigned i = 0; i < VRegs.size(); ++i) - if (!assign(VRegs[i], ArgLocs[ArgLocsStartIndex + i])) + if (!assign(VRegs[i], ArgLocs[ArgLocsStartIndex + i], VT)) return false; return true; } void MipsCallLowering::MipsHandler::setLeastSignificantFirst( - SmallVectorImpl<unsigned> &VRegs) { + SmallVectorImpl<Register> &VRegs) { if (!MIRBuilder.getMF().getDataLayout().isLittleEndian()) std::reverse(VRegs.begin(), VRegs.end()); } bool MipsCallLowering::MipsHandler::handle( ArrayRef<CCValAssign> ArgLocs, ArrayRef<CallLowering::ArgInfo> Args) { - SmallVector<unsigned, 4> VRegs; + SmallVector<Register, 4> VRegs; unsigned SplitLength; const Function &F = MIRBuilder.getMF().getFunction(); const DataLayout &DL = F.getParent()->getDataLayout(); @@ -65,6 +66,8 @@ bool MipsCallLowering::MipsHandler::handle( EVT VT = TLI.getValueType(DL, Args[ArgsIndex].Ty); SplitLength = TLI.getNumRegistersForCallingConv(F.getContext(), F.getCallingConv(), VT); + assert(Args[ArgsIndex].Regs.size() == 1 && "Can't handle multple regs yet"); + if (SplitLength > 1) { VRegs.clear(); MVT RegisterVT = TLI.getRegisterTypeForCallingConv( @@ -72,10 +75,11 @@ bool MipsCallLowering::MipsHandler::handle( for (unsigned i = 0; i < SplitLength; ++i) VRegs.push_back(MRI.createGenericVirtualRegister(LLT{RegisterVT})); - if (!handleSplit(VRegs, ArgLocs, ArgLocsIndex, Args[ArgsIndex].Reg)) + if (!handleSplit(VRegs, ArgLocs, ArgLocsIndex, Args[ArgsIndex].Regs[0], + VT)) return false; } else { - if (!assign(Args[ArgsIndex].Reg, ArgLocs[ArgLocsIndex])) + if (!assign(Args[ArgsIndex].Regs[0], ArgLocs[ArgLocsIndex], VT)) return false; } } @@ -89,24 +93,25 @@ public: : MipsHandler(MIRBuilder, MRI) {} private: - void assignValueToReg(unsigned ValVReg, const CCValAssign &VA) override; + void assignValueToReg(Register ValVReg, const CCValAssign &VA, + const EVT &VT) override; - unsigned getStackAddress(const CCValAssign &VA, + Register getStackAddress(const CCValAssign &VA, MachineMemOperand *&MMO) override; - void assignValueToAddress(unsigned ValVReg, const CCValAssign &VA) override; + void assignValueToAddress(Register ValVReg, const CCValAssign &VA) override; - bool handleSplit(SmallVectorImpl<unsigned> &VRegs, + bool handleSplit(SmallVectorImpl<Register> &VRegs, ArrayRef<CCValAssign> ArgLocs, unsigned ArgLocsStartIndex, - unsigned ArgsReg) override; + Register ArgsReg, const EVT &VT) override; virtual void markPhysRegUsed(unsigned PhysReg) { MIRBuilder.getMBB().addLiveIn(PhysReg); } - void buildLoad(unsigned Val, const CCValAssign &VA) { + void buildLoad(Register Val, const CCValAssign &VA) { MachineMemOperand *MMO; - unsigned Addr = getStackAddress(VA, MMO); + Register Addr = getStackAddress(VA, MMO); MIRBuilder.buildLoad(Val, Addr, *MMO); } }; @@ -127,59 +132,88 @@ private: } // end anonymous namespace -void IncomingValueHandler::assignValueToReg(unsigned ValVReg, - const CCValAssign &VA) { - unsigned PhysReg = VA.getLocReg(); - switch (VA.getLocInfo()) { - case CCValAssign::LocInfo::SExt: - case CCValAssign::LocInfo::ZExt: - case CCValAssign::LocInfo::AExt: { - auto Copy = MIRBuilder.buildCopy(LLT{VA.getLocVT()}, PhysReg); - MIRBuilder.buildTrunc(ValVReg, Copy); - break; - } - default: - MIRBuilder.buildCopy(ValVReg, PhysReg); - break; +void IncomingValueHandler::assignValueToReg(Register ValVReg, + const CCValAssign &VA, + const EVT &VT) { + const MipsSubtarget &STI = + static_cast<const MipsSubtarget &>(MIRBuilder.getMF().getSubtarget()); + Register PhysReg = VA.getLocReg(); + if (VT == MVT::f64 && PhysReg >= Mips::A0 && PhysReg <= Mips::A3) { + const MipsSubtarget &STI = + static_cast<const MipsSubtarget &>(MIRBuilder.getMF().getSubtarget()); + + MIRBuilder + .buildInstr(STI.isFP64bit() ? Mips::BuildPairF64_64 + : Mips::BuildPairF64) + .addDef(ValVReg) + .addUse(PhysReg + (STI.isLittle() ? 0 : 1)) + .addUse(PhysReg + (STI.isLittle() ? 1 : 0)) + .constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(), + *STI.getRegBankInfo()); + markPhysRegUsed(PhysReg); + markPhysRegUsed(PhysReg + 1); + } else if (VT == MVT::f32 && PhysReg >= Mips::A0 && PhysReg <= Mips::A3) { + MIRBuilder.buildInstr(Mips::MTC1) + .addDef(ValVReg) + .addUse(PhysReg) + .constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(), + *STI.getRegBankInfo()); + markPhysRegUsed(PhysReg); + } else { + switch (VA.getLocInfo()) { + case CCValAssign::LocInfo::SExt: + case CCValAssign::LocInfo::ZExt: + case CCValAssign::LocInfo::AExt: { + auto Copy = MIRBuilder.buildCopy(LLT{VA.getLocVT()}, PhysReg); + MIRBuilder.buildTrunc(ValVReg, Copy); + break; + } + default: + MIRBuilder.buildCopy(ValVReg, PhysReg); + break; + } + markPhysRegUsed(PhysReg); } - markPhysRegUsed(PhysReg); } -unsigned IncomingValueHandler::getStackAddress(const CCValAssign &VA, +Register IncomingValueHandler::getStackAddress(const CCValAssign &VA, MachineMemOperand *&MMO) { + MachineFunction &MF = MIRBuilder.getMF(); unsigned Size = alignTo(VA.getValVT().getSizeInBits(), 8) / 8; unsigned Offset = VA.getLocMemOffset(); - MachineFrameInfo &MFI = MIRBuilder.getMF().getFrameInfo(); + MachineFrameInfo &MFI = MF.getFrameInfo(); int FI = MFI.CreateFixedObject(Size, Offset, true); MachinePointerInfo MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI); - MMO = MIRBuilder.getMF().getMachineMemOperand(MPO, MachineMemOperand::MOLoad, - Size, /* Alignment */ 0); - unsigned AddrReg = MRI.createGenericVirtualRegister(LLT::pointer(0, 32)); + const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering(); + unsigned Align = MinAlign(TFL->getStackAlignment(), Offset); + MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, Size, Align); + + Register AddrReg = MRI.createGenericVirtualRegister(LLT::pointer(0, 32)); MIRBuilder.buildFrameIndex(AddrReg, FI); return AddrReg; } -void IncomingValueHandler::assignValueToAddress(unsigned ValVReg, +void IncomingValueHandler::assignValueToAddress(Register ValVReg, const CCValAssign &VA) { if (VA.getLocInfo() == CCValAssign::SExt || VA.getLocInfo() == CCValAssign::ZExt || VA.getLocInfo() == CCValAssign::AExt) { - unsigned LoadReg = MRI.createGenericVirtualRegister(LLT::scalar(32)); + Register LoadReg = MRI.createGenericVirtualRegister(LLT::scalar(32)); buildLoad(LoadReg, VA); MIRBuilder.buildTrunc(ValVReg, LoadReg); } else buildLoad(ValVReg, VA); } -bool IncomingValueHandler::handleSplit(SmallVectorImpl<unsigned> &VRegs, +bool IncomingValueHandler::handleSplit(SmallVectorImpl<Register> &VRegs, ArrayRef<CCValAssign> ArgLocs, unsigned ArgLocsStartIndex, - unsigned ArgsReg) { - if (!assignVRegs(VRegs, ArgLocs, ArgLocsStartIndex)) + Register ArgsReg, const EVT &VT) { + if (!assignVRegs(VRegs, ArgLocs, ArgLocsStartIndex, VT)) return false; setLeastSignificantFirst(VRegs); MIRBuilder.buildMerge(ArgsReg, VRegs); @@ -194,78 +228,111 @@ public: : MipsHandler(MIRBuilder, MRI), MIB(MIB) {} private: - void assignValueToReg(unsigned ValVReg, const CCValAssign &VA) override; + void assignValueToReg(Register ValVReg, const CCValAssign &VA, + const EVT &VT) override; - unsigned getStackAddress(const CCValAssign &VA, + Register getStackAddress(const CCValAssign &VA, MachineMemOperand *&MMO) override; - void assignValueToAddress(unsigned ValVReg, const CCValAssign &VA) override; + void assignValueToAddress(Register ValVReg, const CCValAssign &VA) override; - bool handleSplit(SmallVectorImpl<unsigned> &VRegs, + bool handleSplit(SmallVectorImpl<Register> &VRegs, ArrayRef<CCValAssign> ArgLocs, unsigned ArgLocsStartIndex, - unsigned ArgsReg) override; + Register ArgsReg, const EVT &VT) override; - unsigned extendRegister(unsigned ValReg, const CCValAssign &VA); + Register extendRegister(Register ValReg, const CCValAssign &VA); MachineInstrBuilder &MIB; }; } // end anonymous namespace -void OutgoingValueHandler::assignValueToReg(unsigned ValVReg, - const CCValAssign &VA) { - unsigned PhysReg = VA.getLocReg(); - unsigned ExtReg = extendRegister(ValVReg, VA); - MIRBuilder.buildCopy(PhysReg, ExtReg); - MIB.addUse(PhysReg, RegState::Implicit); +void OutgoingValueHandler::assignValueToReg(Register ValVReg, + const CCValAssign &VA, + const EVT &VT) { + Register PhysReg = VA.getLocReg(); + const MipsSubtarget &STI = + static_cast<const MipsSubtarget &>(MIRBuilder.getMF().getSubtarget()); + + if (VT == MVT::f64 && PhysReg >= Mips::A0 && PhysReg <= Mips::A3) { + MIRBuilder + .buildInstr(STI.isFP64bit() ? Mips::ExtractElementF64_64 + : Mips::ExtractElementF64) + .addDef(PhysReg + (STI.isLittle() ? 1 : 0)) + .addUse(ValVReg) + .addImm(1) + .constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(), + *STI.getRegBankInfo()); + MIRBuilder + .buildInstr(STI.isFP64bit() ? Mips::ExtractElementF64_64 + : Mips::ExtractElementF64) + .addDef(PhysReg + (STI.isLittle() ? 0 : 1)) + .addUse(ValVReg) + .addImm(0) + .constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(), + *STI.getRegBankInfo()); + } else if (VT == MVT::f32 && PhysReg >= Mips::A0 && PhysReg <= Mips::A3) { + MIRBuilder.buildInstr(Mips::MFC1) + .addDef(PhysReg) + .addUse(ValVReg) + .constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(), + *STI.getRegBankInfo()); + } else { + Register ExtReg = extendRegister(ValVReg, VA); + MIRBuilder.buildCopy(PhysReg, ExtReg); + MIB.addUse(PhysReg, RegState::Implicit); + } } -unsigned OutgoingValueHandler::getStackAddress(const CCValAssign &VA, +Register OutgoingValueHandler::getStackAddress(const CCValAssign &VA, MachineMemOperand *&MMO) { + MachineFunction &MF = MIRBuilder.getMF(); + const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering(); + LLT p0 = LLT::pointer(0, 32); LLT s32 = LLT::scalar(32); - unsigned SPReg = MRI.createGenericVirtualRegister(p0); - MIRBuilder.buildCopy(SPReg, Mips::SP); + Register SPReg = MRI.createGenericVirtualRegister(p0); + MIRBuilder.buildCopy(SPReg, Register(Mips::SP)); - unsigned OffsetReg = MRI.createGenericVirtualRegister(s32); + Register OffsetReg = MRI.createGenericVirtualRegister(s32); unsigned Offset = VA.getLocMemOffset(); MIRBuilder.buildConstant(OffsetReg, Offset); - unsigned AddrReg = MRI.createGenericVirtualRegister(p0); + Register AddrReg = MRI.createGenericVirtualRegister(p0); MIRBuilder.buildGEP(AddrReg, SPReg, OffsetReg); MachinePointerInfo MPO = MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset); unsigned Size = alignTo(VA.getValVT().getSizeInBits(), 8) / 8; - MMO = MIRBuilder.getMF().getMachineMemOperand(MPO, MachineMemOperand::MOStore, - Size, /* Alignment */ 0); + unsigned Align = MinAlign(TFL->getStackAlignment(), Offset); + MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOStore, Size, Align); return AddrReg; } -void OutgoingValueHandler::assignValueToAddress(unsigned ValVReg, +void OutgoingValueHandler::assignValueToAddress(Register ValVReg, const CCValAssign &VA) { MachineMemOperand *MMO; - unsigned Addr = getStackAddress(VA, MMO); - unsigned ExtReg = extendRegister(ValVReg, VA); + Register Addr = getStackAddress(VA, MMO); + Register ExtReg = extendRegister(ValVReg, VA); MIRBuilder.buildStore(ExtReg, Addr, *MMO); } -unsigned OutgoingValueHandler::extendRegister(unsigned ValReg, +Register OutgoingValueHandler::extendRegister(Register ValReg, const CCValAssign &VA) { LLT LocTy{VA.getLocVT()}; switch (VA.getLocInfo()) { case CCValAssign::SExt: { - unsigned ExtReg = MRI.createGenericVirtualRegister(LocTy); + Register ExtReg = MRI.createGenericVirtualRegister(LocTy); MIRBuilder.buildSExt(ExtReg, ValReg); return ExtReg; } case CCValAssign::ZExt: { - unsigned ExtReg = MRI.createGenericVirtualRegister(LocTy); + Register ExtReg = MRI.createGenericVirtualRegister(LocTy); MIRBuilder.buildZExt(ExtReg, ValReg); return ExtReg; } case CCValAssign::AExt: { - unsigned ExtReg = MRI.createGenericVirtualRegister(LocTy); + Register ExtReg = MRI.createGenericVirtualRegister(LocTy); MIRBuilder.buildAnyExt(ExtReg, ValReg); return ExtReg; } @@ -278,13 +345,13 @@ unsigned OutgoingValueHandler::extendRegister(unsigned ValReg, llvm_unreachable("unable to extend register"); } -bool OutgoingValueHandler::handleSplit(SmallVectorImpl<unsigned> &VRegs, +bool OutgoingValueHandler::handleSplit(SmallVectorImpl<Register> &VRegs, ArrayRef<CCValAssign> ArgLocs, unsigned ArgLocsStartIndex, - unsigned ArgsReg) { + Register ArgsReg, const EVT &VT) { MIRBuilder.buildUnmerge(VRegs, ArgsReg); setLeastSignificantFirst(VRegs); - if (!assignVRegs(VRegs, ArgLocs, ArgLocsStartIndex)) + if (!assignVRegs(VRegs, ArgLocs, ArgLocsStartIndex, VT)) return false; return true; @@ -295,6 +362,8 @@ static bool isSupportedType(Type *T) { return true; if (T->isPointerTy()) return true; + if (T->isFloatingPointTy()) + return true; return false; } @@ -330,7 +399,7 @@ static void setLocInfo(SmallVectorImpl<CCValAssign> &ArgLocs, bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, - ArrayRef<unsigned> VRegs) const { + ArrayRef<Register> VRegs) const { MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Mips::RetRA); @@ -376,9 +445,9 @@ bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, return true; } -bool MipsCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, - const Function &F, - ArrayRef<unsigned> VRegs) const { +bool MipsCallLowering::lowerFormalArguments( + MachineIRBuilder &MIRBuilder, const Function &F, + ArrayRef<ArrayRef<Register>> VRegs) const { // Quick exit if there aren't any args. if (F.arg_empty()) @@ -444,7 +513,8 @@ bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, if (Arg.Flags.isByVal() || Arg.Flags.isSRet()) return false; } - if (OrigRet.Reg && !isSupportedType(OrigRet.Ty)) + + if (OrigRet.Regs[0] && !isSupportedType(OrigRet.Ty)) return false; MachineFunction &MF = MIRBuilder.getMF(); @@ -457,14 +527,22 @@ bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, MachineInstrBuilder CallSeqStart = MIRBuilder.buildInstr(Mips::ADJCALLSTACKDOWN); - // FIXME: Add support for pic calling sequences, long call sequences for O32, - // N32 and N64. First handle the case when Callee.isReg(). - if (Callee.isReg()) - return false; + const bool IsCalleeGlobalPIC = + Callee.isGlobal() && TM.isPositionIndependent(); - MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert(Mips::JAL); + MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert( + Callee.isReg() || IsCalleeGlobalPIC ? Mips::JALRPseudo : Mips::JAL); MIB.addDef(Mips::SP, RegState::Implicit); - MIB.add(Callee); + if (IsCalleeGlobalPIC) { + Register CalleeReg = + MF.getRegInfo().createGenericVirtualRegister(LLT::pointer(0, 32)); + MachineInstr *CalleeGlobalValue = + MIRBuilder.buildGlobalValue(CalleeReg, Callee.getGlobal()); + if (!Callee.getGlobal()->hasLocalLinkage()) + CalleeGlobalValue->getOperand(1).setTargetFlags(MipsII::MO_GOT_CALL); + MIB.addUse(CalleeReg); + } else + MIB.add(Callee); const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); MIB.addRegMask(TRI->getCallPreservedMask(MF, F.getCallingConv())); @@ -507,10 +585,21 @@ bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, NextStackOffset = alignTo(NextStackOffset, StackAlignment); CallSeqStart.addImm(NextStackOffset).addImm(0); + if (IsCalleeGlobalPIC) { + MIRBuilder.buildCopy( + Register(Mips::GP), + MF.getInfo<MipsFunctionInfo>()->getGlobalBaseRegForGlobalISel()); + MIB.addDef(Mips::GP, RegState::Implicit); + } MIRBuilder.insertInstr(MIB); + if (MIB->getOpcode() == Mips::JALRPseudo) { + const MipsSubtarget &STI = + static_cast<const MipsSubtarget &>(MIRBuilder.getMF().getSubtarget()); + MIB.constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(), + *STI.getRegBankInfo()); + } - if (OrigRet.Reg) { - + if (OrigRet.Regs[0]) { ArgInfos.clear(); SmallVector<unsigned, 8> OrigRetIndices; diff --git a/lib/Target/Mips/MipsCallLowering.h b/lib/Target/Mips/MipsCallLowering.h index 9916b04ef50c..11c2d53ad35d 100644 --- a/lib/Target/Mips/MipsCallLowering.h +++ b/lib/Target/Mips/MipsCallLowering.h @@ -1,9 +1,8 @@ //===- MipsCallLowering.h ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -35,37 +34,39 @@ public: ArrayRef<CallLowering::ArgInfo> Args); protected: - bool assignVRegs(ArrayRef<unsigned> VRegs, ArrayRef<CCValAssign> ArgLocs, - unsigned Index); + bool assignVRegs(ArrayRef<Register> VRegs, ArrayRef<CCValAssign> ArgLocs, + unsigned ArgLocsStartIndex, const EVT &VT); - void setLeastSignificantFirst(SmallVectorImpl<unsigned> &VRegs); + void setLeastSignificantFirst(SmallVectorImpl<Register> &VRegs); MachineIRBuilder &MIRBuilder; MachineRegisterInfo &MRI; private: - bool assign(unsigned VReg, const CCValAssign &VA); + bool assign(Register VReg, const CCValAssign &VA, const EVT &VT); - virtual unsigned getStackAddress(const CCValAssign &VA, + virtual Register getStackAddress(const CCValAssign &VA, MachineMemOperand *&MMO) = 0; - virtual void assignValueToReg(unsigned ValVReg, const CCValAssign &VA) = 0; + virtual void assignValueToReg(Register ValVReg, const CCValAssign &VA, + const EVT &VT) = 0; - virtual void assignValueToAddress(unsigned ValVReg, + virtual void assignValueToAddress(Register ValVReg, const CCValAssign &VA) = 0; - virtual bool handleSplit(SmallVectorImpl<unsigned> &VRegs, + virtual bool handleSplit(SmallVectorImpl<Register> &VRegs, ArrayRef<CCValAssign> ArgLocs, - unsigned ArgLocsStartIndex, unsigned ArgsReg) = 0; + unsigned ArgLocsStartIndex, Register ArgsReg, + const EVT &VT) = 0; }; MipsCallLowering(const MipsTargetLowering &TLI); bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, - ArrayRef<unsigned> VRegs) const override; + ArrayRef<Register> VRegs) const override; bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, - ArrayRef<unsigned> VRegs) const override; + ArrayRef<ArrayRef<Register>> VRegs) const override; bool lowerCall(MachineIRBuilder &MIRBuilder, CallingConv::ID CallConv, const MachineOperand &Callee, const ArgInfo &OrigRet, diff --git a/lib/Target/Mips/MipsCallingConv.td b/lib/Target/Mips/MipsCallingConv.td index b5df78f89a6b..88236d8e9abd 100644 --- a/lib/Target/Mips/MipsCallingConv.td +++ b/lib/Target/Mips/MipsCallingConv.td @@ -1,9 +1,8 @@ //===-- MipsCallingConv.td - Calling Conventions for Mips --*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // This describes the calling conventions for Mips architecture. diff --git a/lib/Target/Mips/MipsCondMov.td b/lib/Target/Mips/MipsCondMov.td index 0d7e3e200b5f..5affbcbc2101 100644 --- a/lib/Target/Mips/MipsCondMov.td +++ b/lib/Target/Mips/MipsCondMov.td @@ -1,9 +1,8 @@ //===-- MipsCondMov.td - Describe Mips Conditional Moves --*- tablegen -*--===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -110,11 +109,11 @@ let AdditionalPredicates = [NotInMicroMips] in { let isCodeGenOnly = 1 in { def MOVZ_I_I64 : CMov_I_I_FT<"movz", GPR32Opnd, GPR64Opnd, II_MOVZ>, - ADD_FM<0, 0xa>, INSN_MIPS4_32_NOT_32R6_64R6; + ADD_FM<0, 0xa>, INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; def MOVZ_I64_I : CMov_I_I_FT<"movz", GPR64Opnd, GPR32Opnd, II_MOVZ>, - ADD_FM<0, 0xa>, INSN_MIPS4_32_NOT_32R6_64R6; + ADD_FM<0, 0xa>, INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; def MOVZ_I64_I64 : CMov_I_I_FT<"movz", GPR64Opnd, GPR64Opnd, II_MOVZ>, - ADD_FM<0, 0xa>, INSN_MIPS4_32_NOT_32R6_64R6; + ADD_FM<0, 0xa>, INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; } def MOVN_I_I : MMRel, CMov_I_I_FT<"movn", GPR32Opnd, GPR32Opnd, II_MOVN>, @@ -122,11 +121,11 @@ let AdditionalPredicates = [NotInMicroMips] in { let isCodeGenOnly = 1 in { def MOVN_I_I64 : CMov_I_I_FT<"movn", GPR32Opnd, GPR64Opnd, II_MOVN>, - ADD_FM<0, 0xb>, INSN_MIPS4_32_NOT_32R6_64R6; + ADD_FM<0, 0xb>, INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; def MOVN_I64_I : CMov_I_I_FT<"movn", GPR64Opnd, GPR32Opnd, II_MOVN>, - ADD_FM<0, 0xb>, INSN_MIPS4_32_NOT_32R6_64R6; + ADD_FM<0, 0xb>, INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; def MOVN_I64_I64 : CMov_I_I_FT<"movn", GPR64Opnd, GPR64Opnd, II_MOVN>, - ADD_FM<0, 0xb>, INSN_MIPS4_32_NOT_32R6_64R6; + ADD_FM<0, 0xb>, INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; } def MOVZ_I_S : MMRel, CMov_I_F_FT<"movz.s", GPR32Opnd, FGR32Opnd, II_MOVZ_S>, CMov_I_F_FM<18, 16>, INSN_MIPS4_32_NOT_32R6_64R6; @@ -156,9 +155,11 @@ let AdditionalPredicates = [NotInMicroMips] in { CMov_I_F_FM<19, 17>, INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; let isCodeGenOnly = 1 in { def MOVZ_I64_D64 : CMov_I_F_FT<"movz.d", GPR64Opnd, FGR64Opnd, II_MOVZ_D>, - CMov_I_F_FM<18, 17>, INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; + CMov_I_F_FM<18, 17>, + INSN_MIPS4_32_NOT_32R6_64R6, GPR_64, FGR_64; def MOVN_I64_D64 : CMov_I_F_FT<"movn.d", GPR64Opnd, FGR64Opnd, II_MOVN_D>, - CMov_I_F_FM<19, 17>, INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; + CMov_I_F_FM<19, 17>, + INSN_MIPS4_32_NOT_32R6_64R6, GPR_64, FGR_64; } } @@ -262,7 +263,7 @@ let AdditionalPredicates = [NotInMicroMips] in { } // For targets that don't have conditional-move instructions // we have to match SELECT nodes with pseudo instructions. -let usesCustomInserter = 1 in { +let usesCustomInserter = 1, hasNoSchedulingInfo = 1 in { class Select_Pseudo<RegisterOperand RC> : PseudoSE<(outs RC:$dst), (ins GPR32Opnd:$cond, RC:$T, RC:$F), [(set RC:$dst, (select GPR32Opnd:$cond, RC:$T, RC:$F))]>, @@ -297,7 +298,7 @@ def PseudoSELECTFP_F_S : SelectFP_Pseudo_F<FGR32Opnd>; def PseudoSELECTFP_F_D32 : SelectFP_Pseudo_F<AFGR64Opnd>, FGR_32; def PseudoSELECTFP_F_D64 : SelectFP_Pseudo_F<FGR64Opnd>, FGR_64; -let usesCustomInserter = 1 in { +let usesCustomInserter = 1, hasNoSchedulingInfo = 1 in { class D_SELECT_CLASS<RegisterOperand RC> : PseudoSE<(outs RC:$dst1, RC:$dst2), (ins GPR32Opnd:$cond, RC:$a1, RC:$a2, RC:$b1, RC:$b2), []>, diff --git a/lib/Target/Mips/MipsConstantIslandPass.cpp b/lib/Target/Mips/MipsConstantIslandPass.cpp index 744523cc6cb9..eea28df7eda1 100644 --- a/lib/Target/Mips/MipsConstantIslandPass.cpp +++ b/lib/Target/Mips/MipsConstantIslandPass.cpp @@ -1,9 +1,8 @@ //===- MipsConstantIslandPass.cpp - Emit Pc Relative loads ----------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -842,9 +841,7 @@ void MipsConstantIslands::updateForInsertedWaterBlock // Next, update WaterList. Specifically, we need to add NewMBB as having // available water after it. - water_iterator IP = - std::lower_bound(WaterList.begin(), WaterList.end(), NewBB, - CompareMBBNumbers); + water_iterator IP = llvm::lower_bound(WaterList, NewBB, CompareMBBNumbers); WaterList.insert(IP, NewBB); } @@ -894,9 +891,7 @@ MipsConstantIslands::splitBlockBeforeInstr(MachineInstr &MI) { // available water after it (but not if it's already there, which happens // when splitting before a conditional branch that is followed by an // unconditional branch - in that case we want to insert NewBB). - water_iterator IP = - std::lower_bound(WaterList.begin(), WaterList.end(), OrigBB, - CompareMBBNumbers); + water_iterator IP = llvm::lower_bound(WaterList, OrigBB, CompareMBBNumbers); MachineBasicBlock* WaterBB = *IP; if (WaterBB == OrigBB) WaterList.insert(std::next(IP), NewBB); diff --git a/lib/Target/Mips/MipsDSPInstrFormats.td b/lib/Target/Mips/MipsDSPInstrFormats.td index 5f0763f5ea46..6f062d0f3c25 100644 --- a/lib/Target/Mips/MipsDSPInstrFormats.td +++ b/lib/Target/Mips/MipsDSPInstrFormats.td @@ -1,9 +1,8 @@ //===- MipsDSPInstrFormats.td - Mips Instruction Formats ---*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MipsDSPInstrInfo.td b/lib/Target/Mips/MipsDSPInstrInfo.td index b9824220b558..daca8b907081 100644 --- a/lib/Target/Mips/MipsDSPInstrInfo.td +++ b/lib/Target/Mips/MipsDSPInstrInfo.td @@ -1,9 +1,8 @@ //===- MipsDSPInstrInfo.td - DSP ASE instructions -*- tablegen ------------*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -516,6 +515,7 @@ class MTHI_DESC_BASE<string instr_asm, RegisterOperand RO, InstrItinClass itin> class BPOSGE32_PSEUDO_DESC_BASE<SDPatternOperator OpNode, InstrItinClass itin> : MipsPseudo<(outs GPR32Opnd:$dst), (ins), [(set GPR32Opnd:$dst, (OpNode))]> { + bit hasNoSchedulingInfo = 1; bit usesCustomInserter = 1; } @@ -1314,7 +1314,9 @@ def PseudoCMPU_LE_QB : PseudoCMP<CMPU_LE_QB>; def PseudoPICK_PH : PseudoPICK<PICK_PH>; def PseudoPICK_QB : PseudoPICK<PICK_QB>; -def PseudoMTLOHI_DSP : PseudoMTLOHI<ACC64DSP, GPR32>; +let AdditionalPredicates = [HasDSP] in { + def PseudoMTLOHI_DSP : PseudoMTLOHI<ACC64DSP, GPR32>; +} // Patterns. class DSPPat<dag pattern, dag result, Predicate pred = HasDSP> : diff --git a/lib/Target/Mips/MipsDelaySlotFiller.cpp b/lib/Target/Mips/MipsDelaySlotFiller.cpp index e3823e0dfdb8..aa07dac86828 100644 --- a/lib/Target/Mips/MipsDelaySlotFiller.cpp +++ b/lib/Target/Mips/MipsDelaySlotFiller.cpp @@ -1,9 +1,8 @@ //===- MipsDelaySlotFiller.cpp - Mips Delay Slot Filler -------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -493,14 +492,12 @@ MemDefsUses::MemDefsUses(const DataLayout &DL, const MachineFrameInfo *MFI_) bool MemDefsUses::hasHazard_(const MachineInstr &MI) { bool HasHazard = false; - SmallVector<ValueType, 4> Objs; // Check underlying object list. + SmallVector<ValueType, 4> Objs; if (getUnderlyingObjects(MI, Objs)) { - for (SmallVectorImpl<ValueType>::const_iterator I = Objs.begin(); - I != Objs.end(); ++I) - HasHazard |= updateDefsUses(*I, MI.mayStore()); - + for (ValueType VT : Objs) + HasHazard |= updateDefsUses(VT, MI.mayStore()); return HasHazard; } @@ -526,33 +523,32 @@ bool MemDefsUses::updateDefsUses(ValueType V, bool MayStore) { bool MemDefsUses:: getUnderlyingObjects(const MachineInstr &MI, SmallVectorImpl<ValueType> &Objects) const { - if (!MI.hasOneMemOperand() || - (!(*MI.memoperands_begin())->getValue() && - !(*MI.memoperands_begin())->getPseudoValue())) + if (!MI.hasOneMemOperand()) return false; - if (const PseudoSourceValue *PSV = - (*MI.memoperands_begin())->getPseudoValue()) { + auto & MMO = **MI.memoperands_begin(); + + if (const PseudoSourceValue *PSV = MMO.getPseudoValue()) { if (!PSV->isAliased(MFI)) return false; Objects.push_back(PSV); return true; } - const Value *V = (*MI.memoperands_begin())->getValue(); + if (const Value *V = MMO.getValue()) { + SmallVector<const Value *, 4> Objs; + GetUnderlyingObjects(V, Objs, DL); - SmallVector<Value *, 4> Objs; - GetUnderlyingObjects(const_cast<Value *>(V), Objs, DL); + for (const Value *UValue : Objs) { + if (!isIdentifiedObject(V)) + return false; - for (SmallVectorImpl<Value *>::iterator I = Objs.begin(), E = Objs.end(); - I != E; ++I) { - if (!isIdentifiedObject(V)) - return false; - - Objects.push_back(*I); + Objects.push_back(UValue); + } + return true; } - return true; + return false; } // Replace Branch with the compact branch instruction. @@ -726,6 +722,7 @@ bool MipsDelaySlotFiller::searchRange(MachineBasicBlock &MBB, IterTy Begin, // but we don't have enough information to make that decision. if (InMicroMipsMode && TII->getInstSizeInBytes(*CurrI) == 2 && (Opcode == Mips::JR || Opcode == Mips::PseudoIndirectBranch || + Opcode == Mips::PseudoIndirectBranch_MM || Opcode == Mips::PseudoReturn || Opcode == Mips::TAILCALL)) continue; // Instructions LWP/SWP and MOVEP should not be in a delay slot as that diff --git a/lib/Target/Mips/MipsEVAInstrFormats.td b/lib/Target/Mips/MipsEVAInstrFormats.td index 61785d0e891a..9820e4dcfc88 100644 --- a/lib/Target/Mips/MipsEVAInstrFormats.td +++ b/lib/Target/Mips/MipsEVAInstrFormats.td @@ -1,9 +1,8 @@ //===- MipsEVAInstrFormats.td - Mips Instruction Formats ---*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/MipsEVAInstrInfo.td b/lib/Target/Mips/MipsEVAInstrInfo.td index ff54b1f17877..73cca8cfa5d9 100644 --- a/lib/Target/Mips/MipsEVAInstrInfo.td +++ b/lib/Target/Mips/MipsEVAInstrInfo.td @@ -1,9 +1,8 @@ //===- MipsEVAInstrInfo.td - EVA ASE instructions -*- tablegen ------------*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/MipsExpandPseudo.cpp b/lib/Target/Mips/MipsExpandPseudo.cpp index acf66d1fb1b2..65d84a6c44a0 100644 --- a/lib/Target/Mips/MipsExpandPseudo.cpp +++ b/lib/Target/Mips/MipsExpandPseudo.cpp @@ -1,9 +1,8 @@ //===-- MipsExpandPseudoInsts.cpp - Expand pseudo instructions ------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/MipsFastISel.cpp b/lib/Target/Mips/MipsFastISel.cpp index 22ade31a72cd..123d3cc242f0 100644 --- a/lib/Target/Mips/MipsFastISel.cpp +++ b/lib/Target/Mips/MipsFastISel.cpp @@ -1,9 +1,8 @@ //===- MipsFastISel.cpp - Mips FastISel implementation --------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// @@ -56,6 +55,7 @@ #include "llvm/IR/Type.h" #include "llvm/IR/User.h" #include "llvm/IR/Value.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCInstrDesc.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSymbol.h" @@ -75,6 +75,8 @@ using namespace llvm; +extern cl::opt<bool> EmitJalrReloc; + namespace { class MipsFastISel final : public FastISel { @@ -951,21 +953,34 @@ bool MipsFastISel::selectBranch(const Instruction *I) { // MachineBasicBlock *TBB = FuncInfo.MBBMap[BI->getSuccessor(0)]; MachineBasicBlock *FBB = FuncInfo.MBBMap[BI->getSuccessor(1)]; - // For now, just try the simplest case where it's fed by a compare. + + // Fold the common case of a conditional branch with a comparison + // in the same block. + unsigned ZExtCondReg = 0; if (const CmpInst *CI = dyn_cast<CmpInst>(BI->getCondition())) { - MVT CIMVT = - TLI.getValueType(DL, CI->getOperand(0)->getType(), true).getSimpleVT(); - if (CIMVT == MVT::i1) + if (CI->hasOneUse() && CI->getParent() == I->getParent()) { + ZExtCondReg = createResultReg(&Mips::GPR32RegClass); + if (!emitCmp(ZExtCondReg, CI)) + return false; + } + } + + // For the general case, we need to mask with 1. + if (ZExtCondReg == 0) { + unsigned CondReg = getRegForValue(BI->getCondition()); + if (CondReg == 0) return false; - unsigned CondReg = getRegForValue(CI); - BuildMI(*BrBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::BGTZ)) - .addReg(CondReg) - .addMBB(TBB); - finishCondBranch(BI->getParent(), TBB, FBB); - return true; + ZExtCondReg = emitIntExt(MVT::i1, CondReg, MVT::i32, true); + if (ZExtCondReg == 0) + return false; } - return false; + + BuildMI(*BrBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::BGTZ)) + .addReg(ZExtCondReg) + .addMBB(TBB); + finishCondBranch(BI->getParent(), TBB, FBB); + return true; } bool MipsFastISel::selectCmp(const Instruction *I) { @@ -1551,6 +1566,16 @@ bool MipsFastISel::fastLowerCall(CallLoweringInfo &CLI) { CLI.Call = MIB; + if (EmitJalrReloc && !Subtarget->inMips16Mode()) { + // Attach callee address to the instruction, let asm printer emit + // .reloc R_MIPS_JALR. + if (Symbol) + MIB.addSym(Symbol, MipsII::MO_JALR); + else + MIB.addSym(FuncInfo.MF->getContext().getOrCreateSymbol( + Addr.getGlobalValue()->getName()), MipsII::MO_JALR); + } + // Finish off the call including any return values. return finishCall(CLI, RetVT, NumBytes); } diff --git a/lib/Target/Mips/MipsFrameLowering.cpp b/lib/Target/Mips/MipsFrameLowering.cpp index 27a85970da6f..8d5eabf59b71 100644 --- a/lib/Target/Mips/MipsFrameLowering.cpp +++ b/lib/Target/Mips/MipsFrameLowering.cpp @@ -1,9 +1,8 @@ //===-- MipsFrameLowering.cpp - Mips Frame Information --------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/MipsFrameLowering.h b/lib/Target/Mips/MipsFrameLowering.h index 0ead56eddd2f..0537cfd1cb30 100644 --- a/lib/Target/Mips/MipsFrameLowering.h +++ b/lib/Target/Mips/MipsFrameLowering.h @@ -1,9 +1,8 @@ //===-- MipsFrameLowering.h - Define frame lowering for Mips ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp index f99f3a1b3e0a..9ba54d6bb73c 100644 --- a/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -1,9 +1,8 @@ //===-- MipsISelDAGToDAG.cpp - A Dag to Dag Inst Selector for Mips --------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/MipsISelDAGToDAG.h b/lib/Target/Mips/MipsISelDAGToDAG.h index 09003459d180..bae3bbf71f3b 100644 --- a/lib/Target/Mips/MipsISelDAGToDAG.h +++ b/lib/Target/Mips/MipsISelDAGToDAG.h @@ -1,9 +1,8 @@ //===---- MipsISelDAGToDAG.h - A Dag to Dag Inst Selector for Mips --------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 8c2a364cdfa9..0ff09007da4b 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -1,9 +1,8 @@ //===- MipsISelLowering.cpp - Mips DAG Lowering Implementation ------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -13,8 +12,8 @@ //===----------------------------------------------------------------------===// #include "MipsISelLowering.h" -#include "InstPrinter/MipsInstPrinter.h" #include "MCTargetDesc/MipsBaseInfo.h" +#include "MCTargetDesc/MipsInstPrinter.h" #include "MCTargetDesc/MipsMCTargetDesc.h" #include "MipsCCState.h" #include "MipsInstrInfo.h" @@ -57,6 +56,7 @@ #include "llvm/IR/GlobalValue.h" #include "llvm/IR/Type.h" #include "llvm/IR/Value.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CodeGen.h" @@ -91,6 +91,8 @@ NoZeroDivCheck("mno-check-zero-division", cl::Hidden, cl::desc("MIPS: Don't trap on integer division by zero."), cl::init(false)); +extern cl::opt<bool> EmitJalrReloc; + static const MCPhysReg Mips64DPRegs[8] = { Mips::D12_64, Mips::D13_64, Mips::D14_64, Mips::D15_64, Mips::D16_64, Mips::D17_64, Mips::D18_64, Mips::D19_64 @@ -362,6 +364,11 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, setOperationAction(ISD::FCOPYSIGN, MVT::f64, Custom); setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); + if (!(TM.Options.NoNaNsFPMath || Subtarget.inAbs2008Mode())) { + setOperationAction(ISD::FABS, MVT::f32, Custom); + setOperationAction(ISD::FABS, MVT::f64, Custom); + } + if (Subtarget.isGP64bit()) { setOperationAction(ISD::GlobalAddress, MVT::i64, Custom); setOperationAction(ISD::BlockAddress, MVT::i64, Custom); @@ -1183,14 +1190,22 @@ bool MipsTargetLowering::isCheapToSpeculateCtlz() const { return Subtarget.hasMips32(); } +bool MipsTargetLowering::shouldFoldConstantShiftPairToMask( + const SDNode *N, CombineLevel Level) const { + if (N->getOperand(0).getValueType().isVector()) + return false; + return true; +} + void MipsTargetLowering::LowerOperationWrapper(SDNode *N, SmallVectorImpl<SDValue> &Results, SelectionDAG &DAG) const { SDValue Res = LowerOperation(SDValue(N, 0), DAG); - for (unsigned I = 0, E = Res->getNumValues(); I != E; ++I) - Results.push_back(Res.getValue(I)); + if (Res) + for (unsigned I = 0, E = Res->getNumValues(); I != E; ++I) + Results.push_back(Res.getValue(I)); } void @@ -1216,6 +1231,7 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const case ISD::VASTART: return lowerVASTART(Op, DAG); case ISD::VAARG: return lowerVAARG(Op, DAG); case ISD::FCOPYSIGN: return lowerFCOPYSIGN(Op, DAG); + case ISD::FABS: return lowerFABS(Op, DAG); case ISD::FRAMEADDR: return lowerFRAMEADDR(Op, DAG); case ISD::RETURNADDR: return lowerRETURNADDR(Op, DAG); case ISD::EH_RETURN: return lowerEH_RETURN(Op, DAG); @@ -1709,7 +1725,7 @@ MipsTargetLowering::emitAtomicCmpSwap(MachineInstr &MI, assert((MI.getOpcode() == Mips::ATOMIC_CMP_SWAP_I32 || MI.getOpcode() == Mips::ATOMIC_CMP_SWAP_I64) && - "Unsupported atomic psseudo for EmitAtomicCmpSwap."); + "Unsupported atomic pseudo for EmitAtomicCmpSwap."); const unsigned Size = MI.getOpcode() == Mips::ATOMIC_CMP_SWAP_I32 ? 4 : 8; @@ -1735,12 +1751,10 @@ MipsTargetLowering::emitAtomicCmpSwap(MachineInstr &MI, // after fast register allocation, the spills will end up outside of the // blocks that their values are defined in, causing livein errors. - unsigned DestCopy = MRI.createVirtualRegister(MRI.getRegClass(Dest)); unsigned PtrCopy = MRI.createVirtualRegister(MRI.getRegClass(Ptr)); unsigned OldValCopy = MRI.createVirtualRegister(MRI.getRegClass(OldVal)); unsigned NewValCopy = MRI.createVirtualRegister(MRI.getRegClass(NewVal)); - BuildMI(*BB, II, DL, TII->get(Mips::COPY), DestCopy).addReg(Dest); BuildMI(*BB, II, DL, TII->get(Mips::COPY), PtrCopy).addReg(Ptr); BuildMI(*BB, II, DL, TII->get(Mips::COPY), OldValCopy).addReg(OldVal); BuildMI(*BB, II, DL, TII->get(Mips::COPY), NewValCopy).addReg(NewVal); @@ -2293,11 +2307,79 @@ MipsTargetLowering::lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const { return lowerFCOPYSIGN32(Op, DAG, Subtarget.hasExtractInsert()); } +static SDValue lowerFABS32(SDValue Op, SelectionDAG &DAG, + bool HasExtractInsert) { + SDLoc DL(Op); + SDValue Res, Const1 = DAG.getConstant(1, DL, MVT::i32); + + // If operand is of type f64, extract the upper 32-bit. Otherwise, bitcast it + // to i32. + SDValue X = (Op.getValueType() == MVT::f32) + ? DAG.getNode(ISD::BITCAST, DL, MVT::i32, Op.getOperand(0)) + : DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, + Op.getOperand(0), Const1); + + // Clear MSB. + if (HasExtractInsert) + Res = DAG.getNode(MipsISD::Ins, DL, MVT::i32, + DAG.getRegister(Mips::ZERO, MVT::i32), + DAG.getConstant(31, DL, MVT::i32), Const1, X); + else { + // TODO: Provide DAG patterns which transform (and x, cst) + // back to a (shl (srl x (clz cst)) (clz cst)) sequence. + SDValue SllX = DAG.getNode(ISD::SHL, DL, MVT::i32, X, Const1); + Res = DAG.getNode(ISD::SRL, DL, MVT::i32, SllX, Const1); + } + + if (Op.getValueType() == MVT::f32) + return DAG.getNode(ISD::BITCAST, DL, MVT::f32, Res); + + // FIXME: For mips32r2, the sequence of (BuildPairF64 (ins (ExtractElementF64 + // Op 1), $zero, 31 1) (ExtractElementF64 Op 0)) and the Op has one use, we + // should be able to drop the usage of mfc1/mtc1 and rewrite the register in + // place. + SDValue LowX = + DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, Op.getOperand(0), + DAG.getConstant(0, DL, MVT::i32)); + return DAG.getNode(MipsISD::BuildPairF64, DL, MVT::f64, LowX, Res); +} + +static SDValue lowerFABS64(SDValue Op, SelectionDAG &DAG, + bool HasExtractInsert) { + SDLoc DL(Op); + SDValue Res, Const1 = DAG.getConstant(1, DL, MVT::i32); + + // Bitcast to integer node. + SDValue X = DAG.getNode(ISD::BITCAST, DL, MVT::i64, Op.getOperand(0)); + + // Clear MSB. + if (HasExtractInsert) + Res = DAG.getNode(MipsISD::Ins, DL, MVT::i64, + DAG.getRegister(Mips::ZERO_64, MVT::i64), + DAG.getConstant(63, DL, MVT::i32), Const1, X); + else { + SDValue SllX = DAG.getNode(ISD::SHL, DL, MVT::i64, X, Const1); + Res = DAG.getNode(ISD::SRL, DL, MVT::i64, SllX, Const1); + } + + return DAG.getNode(ISD::BITCAST, DL, MVT::f64, Res); +} + +SDValue MipsTargetLowering::lowerFABS(SDValue Op, SelectionDAG &DAG) const { + if ((ABI.IsN32() || ABI.IsN64()) && (Op.getValueType() == MVT::f64)) + return lowerFABS64(Op, DAG, Subtarget.hasExtractInsert()); + + return lowerFABS32(Op, DAG, Subtarget.hasExtractInsert()); +} + SDValue MipsTargetLowering:: lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { // check the depth - assert((cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() == 0) && - "Frame address can only be determined for current frame."); + if (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() != 0) { + DAG.getContext()->emitError( + "return address can be determined only for current frame"); + return SDValue(); + } MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); MFI.setFrameAddressIsTaken(true); @@ -2314,8 +2396,11 @@ SDValue MipsTargetLowering::lowerRETURNADDR(SDValue Op, return SDValue(); // check the depth - assert((cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() == 0) && - "Return address can be determined only for current frame."); + if (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() != 0) { + DAG.getContext()->emitError( + "return address can be determined only for current frame"); + return SDValue(); + } MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo &MFI = MF.getFrameInfo(); @@ -2879,6 +2964,54 @@ getOpndList(SmallVectorImpl<SDValue> &Ops, Ops.push_back(InFlag); } +void MipsTargetLowering::AdjustInstrPostInstrSelection(MachineInstr &MI, + SDNode *Node) const { + switch (MI.getOpcode()) { + default: + return; + case Mips::JALR: + case Mips::JALRPseudo: + case Mips::JALR64: + case Mips::JALR64Pseudo: + case Mips::JALR16_MM: + case Mips::JALRC16_MMR6: + case Mips::TAILCALLREG: + case Mips::TAILCALLREG64: + case Mips::TAILCALLR6REG: + case Mips::TAILCALL64R6REG: + case Mips::TAILCALLREG_MM: + case Mips::TAILCALLREG_MMR6: { + if (!EmitJalrReloc || + Subtarget.inMips16Mode() || + !isPositionIndependent() || + Node->getNumOperands() < 1 || + Node->getOperand(0).getNumOperands() < 2) { + return; + } + // We are after the callee address, set by LowerCall(). + // If added to MI, asm printer will emit .reloc R_MIPS_JALR for the + // symbol. + const SDValue TargetAddr = Node->getOperand(0).getOperand(1); + StringRef Sym; + if (const GlobalAddressSDNode *G = + dyn_cast_or_null<const GlobalAddressSDNode>(TargetAddr)) { + Sym = G->getGlobal()->getName(); + } + else if (const ExternalSymbolSDNode *ES = + dyn_cast_or_null<const ExternalSymbolSDNode>(TargetAddr)) { + Sym = ES->getSymbol(); + } + + if (Sym.empty()) + return; + + MachineFunction *MF = MI.getParent()->getParent(); + MCSymbol *S = MF->getContext().getOrCreateSymbol(Sym); + MI.addOperand(MachineOperand::CreateMCSymbol(S, MipsII::MO_JALR)); + } + } +} + /// LowerCall - functions arguments are copied from virtual regs to /// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted. SDValue @@ -2930,7 +3063,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // the maximum out going argument area (including the reserved area), and // preallocates the stack space on entrance to the caller. // - // FIXME: We should do the same for efficency and space. + // FIXME: We should do the same for efficiency and space. // Note: The check on the calling convention below must match // MipsABIInfo::GetCalleeAllocdArgSizeInBytes(). @@ -4007,18 +4140,18 @@ MipsTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { return false; } -EVT MipsTargetLowering::getOptimalMemOpType(uint64_t Size, unsigned DstAlign, - unsigned SrcAlign, - bool IsMemset, bool ZeroMemset, - bool MemcpyStrSrc, - MachineFunction &MF) const { +EVT MipsTargetLowering::getOptimalMemOpType( + uint64_t Size, unsigned DstAlign, unsigned SrcAlign, bool IsMemset, + bool ZeroMemset, bool MemcpyStrSrc, + const AttributeList &FuncAttributes) const { if (Subtarget.hasMips64()) return MVT::i64; return MVT::i32; } -bool MipsTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const { +bool MipsTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT, + bool ForCodeSize) const { if (VT != MVT::f32 && VT != MVT::f64) return false; if (Imm.isNegZero()) diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index e043f133a09f..2db60e9801f1 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -1,9 +1,8 @@ //===- MipsISelLowering.h - Mips DAG Lowering Interface ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -285,6 +284,8 @@ class TargetRegisterClass; bool isCheapToSpeculateCttz() const override; bool isCheapToSpeculateCtlz() const override; + bool shouldFoldConstantShiftPairToMask(const SDNode *N, + CombineLevel Level) const override; /// Return the register type for a given MVT, ensuring vectors are treated /// as a series of gpr sized integers. @@ -341,6 +342,9 @@ class TargetRegisterClass; EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const override; + void AdjustInstrPostInstrSelection(MachineInstr &MI, + SDNode *Node) const override; + void HandleByVal(CCState *, unsigned &, unsigned) const override; unsigned getRegisterByName(const char* RegName, EVT VT, @@ -649,9 +653,11 @@ class TargetRegisterClass; unsigned getInlineAsmMemConstraint(StringRef ConstraintCode) const override { + if (ConstraintCode == "o") + return InlineAsm::Constraint_o; if (ConstraintCode == "R") return InlineAsm::Constraint_R; - else if (ConstraintCode == "ZC") + if (ConstraintCode == "ZC") return InlineAsm::Constraint_ZC; return TargetLowering::getInlineAsmMemConstraint(ConstraintCode); } @@ -666,12 +672,13 @@ class TargetRegisterClass; unsigned SrcAlign, bool IsMemset, bool ZeroMemset, bool MemcpyStrSrc, - MachineFunction &MF) const override; + const AttributeList &FuncAttributes) const override; /// isFPImmLegal - Returns true if the target can instruction select the /// specified FP immediate natively. If false, the legalizer will /// materialize the FP immediate as a load from a constant pool. - bool isFPImmLegal(const APFloat &Imm, EVT VT) const override; + bool isFPImmLegal(const APFloat &Imm, EVT VT, + bool ForCodeSize) const override; unsigned getJumpTableEncoding() const override; bool useSoftFloat() const override; diff --git a/lib/Target/Mips/MipsInstrFPU.td b/lib/Target/Mips/MipsInstrFPU.td index 4cb8574e08f6..e94e107e64c2 100644 --- a/lib/Target/Mips/MipsInstrFPU.td +++ b/lib/Target/Mips/MipsInstrFPU.td @@ -1,9 +1,8 @@ //===-- MipsInstrFPU.td - Mips FPU Instruction Information -*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -143,7 +142,7 @@ multiclass ABSS_M<string opstr, InstrItinClass Itin, SDPatternOperator OpNode= null_frag> { def _D32 : MMRel, ABSS_FT<opstr, AFGR64Opnd, AFGR64Opnd, Itin, OpNode>, FGR_32; - def _D64 : ABSS_FT<opstr, FGR64Opnd, FGR64Opnd, Itin, OpNode>, FGR_64 { + def _D64 : StdMMR6Rel, ABSS_FT<opstr, FGR64Opnd, FGR64Opnd, Itin, OpNode>, FGR_64 { string DecoderNamespace = "MipsFP64"; } } @@ -487,7 +486,7 @@ let isPseudo = 1, isCodeGenOnly = 1 in { def PseudoCVT_D64_L : ABSS_FT<"", FGR64Opnd, GPR64Opnd, II_CVT>; } -let AdditionalPredicates = [NotInMicroMips] in { +let AdditionalPredicates = [NotInMicroMips, UseAbs] in { def FABS_S : MMRel, ABSS_FT<"abs.s", FGR32Opnd, FGR32Opnd, II_ABS, fabs>, ABSS_FM<0x5, 16>, ISA_MIPS1; defm FABS : ABSS_M<"abs.d", II_ABS, fabs>, ABSS_FM<0x5, 17>, ISA_MIPS1; @@ -551,12 +550,7 @@ let AdditionalPredicates = [NotInMicroMips] in { let isMoveReg = 1 in { def FMOV_S : MMRel, ABSS_FT<"mov.s", FGR32Opnd, FGR32Opnd, II_MOV_S>, ABSS_FM<0x6, 16>, ISA_MIPS1; - def FMOV_D32 : MMRel, ABSS_FT<"mov.d", AFGR64Opnd, AFGR64Opnd, II_MOV_D>, - ABSS_FM<0x6, 17>, ISA_MIPS1, FGR_32; - def FMOV_D64 : ABSS_FT<"mov.d", FGR64Opnd, FGR64Opnd, II_MOV_D>, - ABSS_FM<0x6, 17>, ISA_MIPS1, FGR_64 { - let DecoderNamespace = "MipsFP64"; - } + defm FMOV : ABSS_M<"mov.d", II_MOV_D>, ABSS_FM<0x6, 17>, ISA_MIPS1; } // isMoveReg } @@ -793,6 +787,11 @@ def LoadImmDoubleFGR : MipsAsmPseudoInst<(outs StrictlyFGR64Opnd:$rd), "li.d\t$rd, $fpimm">, FGR_64, HARDFLOAT; +def SDC1_M1 : MipsAsmPseudoInst<(outs AFGR64Opnd:$fd), + (ins mem_simm16:$addr), + "s.d\t$fd, $addr">, + FGR_32, ISA_MIPS1, HARDFLOAT; + //===----------------------------------------------------------------------===// // InstAliases. //===----------------------------------------------------------------------===// @@ -805,6 +804,9 @@ def : MipsInstAlias def : MipsInstAlias <"s.d $fd, $addr", (SDC164 FGR64Opnd:$fd, mem_simm16:$addr), 0>, FGR_64, ISA_MIPS2, HARDFLOAT; +def : MipsInstAlias + <"s.d $fd, $addr", (SDC1_M1 AFGR64Opnd:$fd, mem_simm16:$addr), 0>, + FGR_32, ISA_MIPS1, HARDFLOAT; def : MipsInstAlias <"l.s $fd, $addr", (LWC1 FGR32Opnd:$fd, mem_simm16:$addr), 0>, diff --git a/lib/Target/Mips/MipsInstrFormats.td b/lib/Target/Mips/MipsInstrFormats.td index ebbdcdf0df89..14f01514f33f 100644 --- a/lib/Target/Mips/MipsInstrFormats.td +++ b/lib/Target/Mips/MipsInstrFormats.td @@ -1,9 +1,8 @@ //===-- MipsInstrFormats.td - Mips Instruction Formats -----*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -146,6 +145,7 @@ class PseudoSE<dag outs, dag ins, list<dag> pattern, class MipsAsmPseudoInst<dag outs, dag ins, string asmstr>: MipsInst<outs, ins, asmstr, [], IIPseudo, Pseudo> { let isPseudo = 1; + let hasNoSchedulingInfo = 1; let Pattern = []; } //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp index bfb4c775205d..fbd56206b249 100644 --- a/lib/Target/Mips/MipsInstrInfo.cpp +++ b/lib/Target/Mips/MipsInstrInfo.cpp @@ -1,9 +1,8 @@ //===- MipsInstrInfo.cpp - Mips Instruction Information -------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -578,7 +577,8 @@ unsigned MipsInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { switch (MI.getOpcode()) { default: return MI.getDesc().getSize(); - case TargetOpcode::INLINEASM: { // Inline Asm: Variable size. + case TargetOpcode::INLINEASM: + case TargetOpcode::INLINEASM_BR: { // Inline Asm: Variable size. const MachineFunction *MF = MI.getParent()->getParent(); const char *AsmStr = MI.getOperand(0).getSymbolName(); return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo()); @@ -653,6 +653,16 @@ MipsInstrInfo::genInstrWithNewOpc(unsigned NewOpc, MIB.addImm(0); + // If I has an MCSymbol operand (used by asm printer, to emit R_MIPS_JALR), + // add it to the new instruction. + for (unsigned J = I->getDesc().getNumOperands(), E = I->getNumOperands(); + J < E; ++J) { + const MachineOperand &MO = I->getOperand(J); + if (MO.isMCSymbol() && (MO.getTargetFlags() & MipsII::MO_JALR)) + MIB.addSym(MO.getMCSymbol(), MipsII::MO_JALR); + } + + } else { for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) { if (BranchWithZeroOperand && (unsigned)ZeroOperandPosition == J) @@ -825,7 +835,8 @@ MipsInstrInfo::getSerializableDirectMachineOperandTargetFlags() const { {MO_GOT_HI16, "mips-got-hi16"}, {MO_GOT_LO16, "mips-got-lo16"}, {MO_CALL_HI16, "mips-call-hi16"}, - {MO_CALL_LO16, "mips-call-lo16"} + {MO_CALL_LO16, "mips-call-lo16"}, + {MO_JALR, "mips-jalr"} }; return makeArrayRef(Flags); } diff --git a/lib/Target/Mips/MipsInstrInfo.h b/lib/Target/Mips/MipsInstrInfo.h index 9d27b8f66211..a626c0c3fdb8 100644 --- a/lib/Target/Mips/MipsInstrInfo.h +++ b/lib/Target/Mips/MipsInstrInfo.h @@ -1,9 +1,8 @@ //===- MipsInstrInfo.h - Mips Instruction Information -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index d9398b7d6024..a4e85a38ab28 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -1,9 +1,8 @@ //===- MipsInstrInfo.td - Target Description for Mips Target -*- tablegen -*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -221,6 +220,8 @@ def IsNotN64 : Predicate<"!Subtarget->isABI_N64()">; def RelocNotPIC : Predicate<"!TM.isPositionIndependent()">; def RelocPIC : Predicate<"TM.isPositionIndependent()">; def NoNaNsFPMath : Predicate<"TM.Options.NoNaNsFPMath">; +def UseAbs : Predicate<"Subtarget->inAbs2008Mode() ||" + "TM.Options.NoNaNsFPMath">; def HasStdEnc : Predicate<"Subtarget->hasStandardEncoding()">, AssemblerPredicate<"!FeatureMips16">; def NotDSP : Predicate<"!Subtarget->hasDSP()">; @@ -1623,11 +1624,15 @@ let isCall=1, hasDelaySlot=1, isCTI=1, Defs = [RA] in { class JumpLinkRegPseudo<RegisterOperand RO, Instruction JALRInst, Register RetReg, RegisterOperand ResRO = RO>: PseudoSE<(outs), (ins RO:$rs), [(MipsJmpLink RO:$rs)], II_JALR>, - PseudoInstExpansion<(JALRInst RetReg, ResRO:$rs)>; + PseudoInstExpansion<(JALRInst RetReg, ResRO:$rs)> { + let hasPostISelHook = 1; + } class JumpLinkReg<string opstr, RegisterOperand RO>: InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"), - [], II_JALR, FrmR, opstr>; + [], II_JALR, FrmR, opstr> { + let hasPostISelHook = 1; + } class BGEZAL_FT<string opstr, DAGOperand opnd, RegisterOperand RO> : @@ -1646,7 +1651,9 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, hasDelaySlot = 1, class TailCallReg<Instruction JumpInst, RegisterOperand RO> : PseudoSE<(outs), (ins RO:$rs), [(MipsTailCall RO:$rs)], II_JR>, - PseudoInstExpansion<(JumpInst RO:$rs)>; + PseudoInstExpansion<(JumpInst RO:$rs)> { + let hasPostISelHook = 1; + } } class BAL_BR_Pseudo<Instruction RealInst, DAGOperand opnd> : @@ -1844,7 +1851,9 @@ class InsBase<string opstr, RegisterOperand RO, Operand PosOpnd, // Atomic instructions with 2 source operands (ATOMIC_SWAP & ATOMIC_LOAD_*). class Atomic2Ops<PatFrag Op, RegisterClass DRC> : PseudoSE<(outs DRC:$dst), (ins PtrRC:$ptr, DRC:$incr), - [(set DRC:$dst, (Op iPTR:$ptr, DRC:$incr))]>; + [(set DRC:$dst, (Op iPTR:$ptr, DRC:$incr))]> { + let hasNoSchedulingInfo = 1; +} class Atomic2OpsPostRA<RegisterClass RC> : PseudoSE<(outs RC:$dst), (ins PtrRC:$ptr, RC:$incr), []> { @@ -1861,7 +1870,9 @@ class Atomic2OpsSubwordPostRA<RegisterClass RC> : // during ISelLowering, which produces the PostRA version of this instruction. class AtomicCmpSwap<PatFrag Op, RegisterClass DRC> : PseudoSE<(outs DRC:$dst), (ins PtrRC:$ptr, DRC:$cmp, DRC:$swap), - [(set DRC:$dst, (Op iPTR:$ptr, DRC:$cmp, DRC:$swap))]>; + [(set DRC:$dst, (Op iPTR:$ptr, DRC:$cmp, DRC:$swap))]> { + let hasNoSchedulingInfo = 1; +} class AtomicCmpSwapPostRA<RegisterClass RC> : PseudoSE<(outs RC:$dst), (ins PtrRC:$ptr, RC:$cmp, RC:$swap), []> { @@ -1876,7 +1887,6 @@ class AtomicCmpSwapSubwordPostRA<RegisterClass RC> : let mayStore = 1; } - class LLBase<string opstr, RegisterOperand RO, DAGOperand MO = mem> : InstSE<(outs RO:$rt), (ins MO:$addr), !strconcat(opstr, "\t$rt, $addr"), [], II_LL, FrmI, opstr> { @@ -1928,7 +1938,7 @@ let isReturn=1, isTerminator=1, isBarrier=1, hasCtrlDep=1, isCTI=1 in { def ERet : PseudoSE<(outs), (ins), [(MipsERet)]>; } -let Defs = [SP], Uses = [SP], hasSideEffects = 1 in { +let Defs = [SP], Uses = [SP], hasSideEffects = 1, hasNoSchedulingInfo = 1 in { def ADJCALLSTACKDOWN : MipsPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), [(callseq_start timm:$amt1, timm:$amt2)]>; def ADJCALLSTACKUP : MipsPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), @@ -2004,17 +2014,25 @@ let isPseudo = 1, isCodeGenOnly = 1, hasNoSchedulingInfo = 1 in { // Expands to: lui $dst, %highest/%higher/%hi/%lo($tgt - $baltgt) def LONG_BRANCH_LUi : PseudoSE<(outs GPR32Opnd:$dst), - (ins brtarget:$tgt, brtarget:$baltgt), []>; + (ins brtarget:$tgt, brtarget:$baltgt), []> { + bit hasNoSchedulingInfo = 1; +} // Expands to: lui $dst, highest/%higher/%hi/%lo($tgt) def LONG_BRANCH_LUi2Op : PseudoSE<(outs GPR32Opnd:$dst), - (ins brtarget:$tgt), []>; + (ins brtarget:$tgt), []> { + bit hasNoSchedulingInfo = 1; +} // Expands to: addiu $dst, $src, %highest/%higher/%hi/%lo($tgt - $baltgt) def LONG_BRANCH_ADDiu : PseudoSE<(outs GPR32Opnd:$dst), - (ins GPR32Opnd:$src, brtarget:$tgt, brtarget:$baltgt), []>; + (ins GPR32Opnd:$src, brtarget:$tgt, brtarget:$baltgt), []> { + bit hasNoSchedulingInfo = 1; +} // Expands to: addiu $dst, $src, %highest/%higher/%hi/%lo($tgt) def LONG_BRANCH_ADDiu2Op : PseudoSE<(outs GPR32Opnd:$dst), - (ins GPR32Opnd:$src, brtarget:$tgt), []>; + (ins GPR32Opnd:$src, brtarget:$tgt), []> { + bit hasNoSchedulingInfo = 1; +} //===----------------------------------------------------------------------===// // Instruction definition @@ -2117,7 +2135,7 @@ let AdditionalPredicates = [NotInMicroMips] in { LW_FM<0x28>, ISA_MIPS1; def SH : Store<"sh", GPR32Opnd, truncstorei16, II_SH>, MMRel, LW_FM<0x29>, ISA_MIPS1; - def SW : Store<"sw", GPR32Opnd, store, II_SW>, MMRel, LW_FM<0x2b>, ISA_MIPS1; + def SW : StdMMR6Rel, Store<"sw", GPR32Opnd, store, II_SW>, MMRel, LW_FM<0x2b>, ISA_MIPS1; } /// load/store left/right @@ -2324,12 +2342,12 @@ def SDT_MipsEHRET : SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisPtrTy<1>]>; def MIPSehret : SDNode<"MipsISD::EH_RETURN", SDT_MipsEHRET, [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; -let Uses = [V0, V1], isTerminator = 1, isReturn = 1, isBarrier = 1, isCTI = 1 in { +let Uses = [V0, V1], isTerminator = 1, isReturn = 1, + isBarrier = 1, isCTI = 1, hasNoSchedulingInfo = 1 in { def MIPSeh_return32 : MipsPseudo<(outs), (ins GPR32:$spoff, GPR32:$dst), - [(MIPSehret GPR32:$spoff, GPR32:$dst)]>; - def MIPSeh_return64 : MipsPseudo<(outs), (ins GPR64:$spoff, - GPR64:$dst), - [(MIPSehret GPR64:$spoff, GPR64:$dst)]>; + [(MIPSehret GPR32:$spoff, GPR32:$dst)]>; + def MIPSeh_return64 : MipsPseudo<(outs), (ins GPR64:$spoff, GPR64:$dst), + [(MIPSehret GPR64:$spoff, GPR64:$dst)]>; } /// Multiply and Divide Instructions. @@ -2675,18 +2693,64 @@ let AdditionalPredicates = [NotInMicroMips] in { (SUBu GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>, ISA_MIPS1; def : MipsInstAlias<"negu $rt", (SUBu GPR32Opnd:$rt, ZERO, GPR32Opnd:$rt), 1>, ISA_MIPS1; + + def SGE : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), + (ins GPR32Opnd:$rs, GPR32Opnd:$rt), + "sge\t$rd, $rs, $rt">, ISA_MIPS1; + def : MipsInstAlias<"sge $rs, $rt", + (SGE GPR32Opnd:$rs, GPR32Opnd:$rs, GPR32Opnd:$rt), 0>, + ISA_MIPS1; + def SGEImm : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), + (ins GPR32Opnd:$rs, simm32:$imm), + "sge\t$rd, $rs, $imm">, GPR_32; + def : MipsInstAlias<"sge $rs, $imm", (SGEImm GPR32Opnd:$rs, + GPR32Opnd:$rs, + simm32:$imm), 0>, + GPR_32; + + def SGEU : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), + (ins GPR32Opnd:$rs, GPR32Opnd:$rt), + "sgeu\t$rd, $rs, $rt">, ISA_MIPS1; + def : MipsInstAlias<"sgeu $rs, $rt", + (SGEU GPR32Opnd:$rs, GPR32Opnd:$rs, GPR32Opnd:$rt), 0>, + ISA_MIPS1; + def SGEUImm : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), + (ins GPR32Opnd:$rs, uimm32_coerced:$imm), + "sgeu\t$rd, $rs, $imm">, GPR_32; + def : MipsInstAlias<"sgeu $rs, $imm", (SGEUImm GPR32Opnd:$rs, + GPR32Opnd:$rs, + uimm32_coerced:$imm), 0>, + GPR_32; + def : MipsInstAlias< "sgt $rd, $rs, $rt", (SLT GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>, ISA_MIPS1; def : MipsInstAlias< "sgt $rs, $rt", (SLT GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>, ISA_MIPS1; + + def SGTImm : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), + (ins GPR32Opnd:$rs, simm32:$imm), + "sgt\t$rd, $rs, $imm">, GPR_32; + def : MipsInstAlias<"sgt $rs, $imm", (SGTImm GPR32Opnd:$rs, + GPR32Opnd:$rs, + simm32:$imm), 0>, + GPR_32; def : MipsInstAlias< "sgtu $rd, $rs, $rt", (SLTu GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>, ISA_MIPS1; def : MipsInstAlias< "sgtu $$rs, $rt", (SLTu GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>, ISA_MIPS1; + + def SGTUImm : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), + (ins GPR32Opnd:$rs, uimm32_coerced:$imm), + "sgtu\t$rd, $rs, $imm">, GPR_32; + def : MipsInstAlias<"sgtu $rs, $imm", (SGTUImm GPR32Opnd:$rs, + GPR32Opnd:$rs, + uimm32_coerced:$imm), 0>, + GPR_32; + def : MipsInstAlias< "not $rt, $rs", (NOR GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>, ISA_MIPS1; @@ -2737,14 +2801,14 @@ let AdditionalPredicates = [NotInMicroMips] in { def : MipsInstAlias<"bnez $rs,$offset", (BNE GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>, ISA_MIPS1; - def : MipsInstAlias<"bnezl $rs,$offset", - (BNEL GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>, + def : MipsInstAlias<"bnezl $rs, $offset", + (BNEL GPR32Opnd:$rs, ZERO, brtarget:$offset), 1>, ISA_MIPS2; def : MipsInstAlias<"beqz $rs,$offset", (BEQ GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>, ISA_MIPS1; - def : MipsInstAlias<"beqzl $rs,$offset", - (BEQL GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>, + def : MipsInstAlias<"beqzl $rs, $offset", + (BEQL GPR32Opnd:$rs, ZERO, brtarget:$offset), 1>, ISA_MIPS2; def : MipsInstAlias<"syscall", (SYSCALL 0), 1>, ISA_MIPS1; diff --git a/lib/Target/Mips/MipsInstructionSelector.cpp b/lib/Target/Mips/MipsInstructionSelector.cpp index b041590ee343..45a47ad3c087 100644 --- a/lib/Target/Mips/MipsInstructionSelector.cpp +++ b/lib/Target/Mips/MipsInstructionSelector.cpp @@ -1,9 +1,8 @@ //===- MipsInstructionSelector.cpp ------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// \file @@ -12,6 +11,8 @@ /// \todo This should be generated by TableGen. //===----------------------------------------------------------------------===// +#include "MCTargetDesc/MipsInstPrinter.h" +#include "MipsMachineFunction.h" #include "MipsRegisterBankInfo.h" #include "MipsTargetMachine.h" #include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h" @@ -37,6 +38,12 @@ public: private: bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const; + bool materialize32BitImm(Register DestReg, APInt Imm, + MachineIRBuilder &B) const; + bool selectCopy(MachineInstr &I, MachineRegisterInfo &MRI) const; + const TargetRegisterClass * + getRegClassForTypeOnBank(unsigned OpSize, const RegisterBank &RB, + const RegisterBankInfo &RBI) const; const MipsTargetMachine &TM; const MipsSubtarget &STI; @@ -74,15 +81,24 @@ MipsInstructionSelector::MipsInstructionSelector( { } -static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, - MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, - const RegisterBankInfo &RBI) { - unsigned DstReg = I.getOperand(0).getReg(); +bool MipsInstructionSelector::selectCopy(MachineInstr &I, + MachineRegisterInfo &MRI) const { + Register DstReg = I.getOperand(0).getReg(); if (TargetRegisterInfo::isPhysicalRegister(DstReg)) return true; - const TargetRegisterClass *RC = &Mips::GPR32RegClass; + const RegisterBank *RegBank = RBI.getRegBank(DstReg, MRI, TRI); + const unsigned DstSize = MRI.getType(DstReg).getSizeInBits(); + const TargetRegisterClass *RC = &Mips::GPR32RegClass; + if (RegBank->getID() == Mips::FPRBRegBankID) { + if (DstSize == 32) + RC = &Mips::FGR32RegClass; + else if (DstSize == 64) + RC = STI.isFP64bit() ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass; + else + llvm_unreachable("Unsupported destination size"); + } if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) { LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode()) << " operand\n"); @@ -91,6 +107,102 @@ static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, return true; } +const TargetRegisterClass *MipsInstructionSelector::getRegClassForTypeOnBank( + unsigned OpSize, const RegisterBank &RB, + const RegisterBankInfo &RBI) const { + if (RB.getID() == Mips::GPRBRegBankID) + return &Mips::GPR32RegClass; + + if (RB.getID() == Mips::FPRBRegBankID) + return OpSize == 32 + ? &Mips::FGR32RegClass + : STI.hasMips32r6() || STI.isFP64bit() ? &Mips::FGR64RegClass + : &Mips::AFGR64RegClass; + + llvm_unreachable("getRegClassForTypeOnBank can't find register class."); + return nullptr; +} + +bool MipsInstructionSelector::materialize32BitImm(Register DestReg, APInt Imm, + MachineIRBuilder &B) const { + assert(Imm.getBitWidth() == 32 && "Unsupported immediate size."); + // Ori zero extends immediate. Used for values with zeros in high 16 bits. + if (Imm.getHiBits(16).isNullValue()) { + MachineInstr *Inst = B.buildInstr(Mips::ORi, {DestReg}, {Register(Mips::ZERO)}) + .addImm(Imm.getLoBits(16).getLimitedValue()); + return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI); + } + // Lui places immediate in high 16 bits and sets low 16 bits to zero. + if (Imm.getLoBits(16).isNullValue()) { + MachineInstr *Inst = B.buildInstr(Mips::LUi, {DestReg}, {}) + .addImm(Imm.getHiBits(16).getLimitedValue()); + return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI); + } + // ADDiu sign extends immediate. Used for values with 1s in high 17 bits. + if (Imm.isSignedIntN(16)) { + MachineInstr *Inst = B.buildInstr(Mips::ADDiu, {DestReg}, {Register(Mips::ZERO)}) + .addImm(Imm.getLoBits(16).getLimitedValue()); + return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI); + } + // Values that cannot be materialized with single immediate instruction. + Register LUiReg = B.getMRI()->createVirtualRegister(&Mips::GPR32RegClass); + MachineInstr *LUi = B.buildInstr(Mips::LUi, {LUiReg}, {}) + .addImm(Imm.getHiBits(16).getLimitedValue()); + MachineInstr *ORi = B.buildInstr(Mips::ORi, {DestReg}, {LUiReg}) + .addImm(Imm.getLoBits(16).getLimitedValue()); + if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI)) + return false; + if (!constrainSelectedInstRegOperands(*ORi, TII, TRI, RBI)) + return false; + return true; +} + +/// Returning Opc indicates that we failed to select MIPS instruction opcode. +static unsigned selectLoadStoreOpCode(unsigned Opc, unsigned MemSizeInBytes, + unsigned RegBank, bool isFP64) { + bool isStore = Opc == TargetOpcode::G_STORE; + if (RegBank == Mips::GPRBRegBankID) { + if (isStore) + switch (MemSizeInBytes) { + case 4: + return Mips::SW; + case 2: + return Mips::SH; + case 1: + return Mips::SB; + default: + return Opc; + } + else + // Unspecified extending load is selected into zeroExtending load. + switch (MemSizeInBytes) { + case 4: + return Mips::LW; + case 2: + return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LH : Mips::LHu; + case 1: + return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LB : Mips::LBu; + default: + return Opc; + } + } + + if (RegBank == Mips::FPRBRegBankID) { + switch (MemSizeInBytes) { + case 4: + return isStore ? Mips::SWC1 : Mips::LWC1; + case 8: + if (isFP64) + return isStore ? Mips::SDC164 : Mips::LDC164; + else + return isStore ? Mips::SDC1 : Mips::LDC1; + default: + return Opc; + } + } + return Opc; +} + bool MipsInstructionSelector::select(MachineInstr &I, CodeGenCoverage &CoverageInfo) const { @@ -100,19 +212,52 @@ bool MipsInstructionSelector::select(MachineInstr &I, if (!isPreISelGenericOpcode(I.getOpcode())) { if (I.isCopy()) - return selectCopy(I, TII, MRI, TRI, RBI); + return selectCopy(I, MRI); return true; } - if (selectImpl(I, CoverageInfo)) { + if (I.getOpcode() == Mips::G_MUL) { + MachineInstr *Mul = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MUL)) + .add(I.getOperand(0)) + .add(I.getOperand(1)) + .add(I.getOperand(2)); + if (!constrainSelectedInstRegOperands(*Mul, TII, TRI, RBI)) + return false; + Mul->getOperand(3).setIsDead(true); + Mul->getOperand(4).setIsDead(true); + + I.eraseFromParent(); return true; } + if (selectImpl(I, CoverageInfo)) + return true; + MachineInstr *MI = nullptr; using namespace TargetOpcode; switch (I.getOpcode()) { + case G_UMULH: { + Register PseudoMULTuReg = MRI.createVirtualRegister(&Mips::ACC64RegClass); + MachineInstr *PseudoMULTu, *PseudoMove; + + PseudoMULTu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoMULTu)) + .addDef(PseudoMULTuReg) + .add(I.getOperand(1)) + .add(I.getOperand(2)); + if (!constrainSelectedInstRegOperands(*PseudoMULTu, TII, TRI, RBI)) + return false; + + PseudoMove = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoMFHI)) + .addDef(I.getOperand(0).getReg()) + .addUse(PseudoMULTuReg); + if (!constrainSelectedInstRegOperands(*PseudoMove, TII, TRI, RBI)) + return false; + + I.eraseFromParent(); + return true; + } case G_GEP: { MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu)) .add(I.getOperand(0)) @@ -127,16 +272,46 @@ bool MipsInstructionSelector::select(MachineInstr &I, .addImm(0); break; } + case G_BRCOND: { + MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::BNE)) + .add(I.getOperand(0)) + .addUse(Mips::ZERO) + .add(I.getOperand(1)); + break; + } + case G_PHI: { + const Register DestReg = I.getOperand(0).getReg(); + const unsigned OpSize = MRI.getType(DestReg).getSizeInBits(); + + const TargetRegisterClass *DefRC = nullptr; + if (TargetRegisterInfo::isPhysicalRegister(DestReg)) + DefRC = TRI.getRegClass(DestReg); + else + DefRC = getRegClassForTypeOnBank(OpSize, + *RBI.getRegBank(DestReg, MRI, TRI), RBI); + + I.setDesc(TII.get(TargetOpcode::PHI)); + return RBI.constrainGenericRegister(DestReg, *DefRC, MRI); + } case G_STORE: - case G_LOAD: { - const unsigned DestReg = I.getOperand(0).getReg(); + case G_LOAD: + case G_ZEXTLOAD: + case G_SEXTLOAD: { + const Register DestReg = I.getOperand(0).getReg(); const unsigned DestRegBank = RBI.getRegBank(DestReg, MRI, TRI)->getID(); const unsigned OpSize = MRI.getType(DestReg).getSizeInBits(); + const unsigned OpMemSizeInBytes = (*I.memoperands_begin())->getSize(); - if (DestRegBank != Mips::GPRBRegBankID || OpSize != 32) + if (DestRegBank == Mips::GPRBRegBankID && OpSize != 32) return false; - const unsigned NewOpc = I.getOpcode() == G_STORE ? Mips::SW : Mips::LW; + if (DestRegBank == Mips::FPRBRegBankID && OpSize != 32 && OpSize != 64) + return false; + + const unsigned NewOpc = selectLoadStoreOpCode( + I.getOpcode(), OpMemSizeInBytes, DestRegBank, STI.isFP64bit()); + if (NewOpc == I.getOpcode()) + return false; MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc)) .add(I.getOperand(0)) @@ -149,7 +324,7 @@ bool MipsInstructionSelector::select(MachineInstr &I, case G_UREM: case G_SDIV: case G_SREM: { - unsigned HILOReg = MRI.createVirtualRegister(&Mips::ACC64RegClass); + Register HILOReg = MRI.createVirtualRegister(&Mips::ACC64RegClass); bool IsSigned = I.getOpcode() == G_SREM || I.getOpcode() == G_SDIV; bool IsDiv = I.getOpcode() == G_UDIV || I.getOpcode() == G_SDIV; @@ -182,58 +357,150 @@ bool MipsInstructionSelector::select(MachineInstr &I, break; } case G_CONSTANT: { - int Imm = I.getOperand(1).getCImm()->getValue().getLimitedValue(); - unsigned LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass); - MachineInstr *LUi, *ORi; + MachineIRBuilder B(I); + if (!materialize32BitImm(I.getOperand(0).getReg(), + I.getOperand(1).getCImm()->getValue(), B)) + return false; - LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi)) - .addDef(LUiReg) - .addImm(Imm >> 16); + I.eraseFromParent(); + return true; + } + case G_FCONSTANT: { + const APFloat &FPimm = I.getOperand(1).getFPImm()->getValueAPF(); + APInt APImm = FPimm.bitcastToAPInt(); + unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits(); - ORi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ORi)) - .addDef(I.getOperand(0).getReg()) - .addUse(LUiReg) - .addImm(Imm & 0xFFFF); + if (Size == 32) { + Register GPRReg = MRI.createVirtualRegister(&Mips::GPR32RegClass); + MachineIRBuilder B(I); + if (!materialize32BitImm(GPRReg, APImm, B)) + return false; + + MachineInstrBuilder MTC1 = + B.buildInstr(Mips::MTC1, {I.getOperand(0).getReg()}, {GPRReg}); + if (!MTC1.constrainAllUses(TII, TRI, RBI)) + return false; + } + if (Size == 64) { + Register GPRRegHigh = MRI.createVirtualRegister(&Mips::GPR32RegClass); + Register GPRRegLow = MRI.createVirtualRegister(&Mips::GPR32RegClass); + MachineIRBuilder B(I); + if (!materialize32BitImm(GPRRegHigh, APImm.getHiBits(32).trunc(32), B)) + return false; + if (!materialize32BitImm(GPRRegLow, APImm.getLoBits(32).trunc(32), B)) + return false; - if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI)) + MachineInstrBuilder PairF64 = B.buildInstr( + STI.isFP64bit() ? Mips::BuildPairF64_64 : Mips::BuildPairF64, + {I.getOperand(0).getReg()}, {GPRRegLow, GPRRegHigh}); + if (!PairF64.constrainAllUses(TII, TRI, RBI)) + return false; + } + + I.eraseFromParent(); + return true; + } + case G_FABS: { + unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits(); + unsigned FABSOpcode = + Size == 32 ? Mips::FABS_S + : STI.isFP64bit() ? Mips::FABS_D64 : Mips::FABS_D32; + MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(FABSOpcode)) + .add(I.getOperand(0)) + .add(I.getOperand(1)); + break; + } + case G_FPTOSI: { + unsigned FromSize = MRI.getType(I.getOperand(1).getReg()).getSizeInBits(); + unsigned ToSize = MRI.getType(I.getOperand(0).getReg()).getSizeInBits(); + (void)ToSize; + assert((ToSize == 32) && "Unsupported integer size for G_FPTOSI"); + assert((FromSize == 32 || FromSize == 64) && + "Unsupported floating point size for G_FPTOSI"); + + unsigned Opcode; + if (FromSize == 32) + Opcode = Mips::TRUNC_W_S; + else + Opcode = STI.isFP64bit() ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32; + unsigned ResultInFPR = MRI.createVirtualRegister(&Mips::FGR32RegClass); + MachineInstr *Trunc = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode)) + .addDef(ResultInFPR) + .addUse(I.getOperand(1).getReg()); + if (!constrainSelectedInstRegOperands(*Trunc, TII, TRI, RBI)) return false; - if (!constrainSelectedInstRegOperands(*ORi, TII, TRI, RBI)) + + MachineInstr *Move = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MFC1)) + .addDef(I.getOperand(0).getReg()) + .addUse(ResultInFPR); + if (!constrainSelectedInstRegOperands(*Move, TII, TRI, RBI)) return false; I.eraseFromParent(); return true; } case G_GLOBAL_VALUE: { - if (MF.getTarget().isPositionIndependent()) - return false; - const llvm::GlobalValue *GVal = I.getOperand(1).getGlobal(); - unsigned LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass); - MachineInstr *LUi, *ADDiu; + if (MF.getTarget().isPositionIndependent()) { + MachineInstr *LWGOT = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LW)) + .addDef(I.getOperand(0).getReg()) + .addReg(MF.getInfo<MipsFunctionInfo>() + ->getGlobalBaseRegForGlobalISel()) + .addGlobalAddress(GVal); + // Global Values that don't have local linkage are handled differently + // when they are part of call sequence. MipsCallLowering::lowerCall + // creates G_GLOBAL_VALUE instruction as part of call sequence and adds + // MO_GOT_CALL flag when Callee doesn't have local linkage. + if (I.getOperand(1).getTargetFlags() == MipsII::MO_GOT_CALL) + LWGOT->getOperand(2).setTargetFlags(MipsII::MO_GOT_CALL); + else + LWGOT->getOperand(2).setTargetFlags(MipsII::MO_GOT); + LWGOT->addMemOperand( + MF, MF.getMachineMemOperand(MachinePointerInfo::getGOT(MF), + MachineMemOperand::MOLoad, 4, 4)); + if (!constrainSelectedInstRegOperands(*LWGOT, TII, TRI, RBI)) + return false; - LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi)) - .addDef(LUiReg) - .addGlobalAddress(GVal); - LUi->getOperand(1).setTargetFlags(MipsII::MO_ABS_HI); + if (GVal->hasLocalLinkage()) { + Register LWGOTDef = MRI.createVirtualRegister(&Mips::GPR32RegClass); + LWGOT->getOperand(0).setReg(LWGOTDef); - ADDiu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu)) + MachineInstr *ADDiu = + BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu)) .addDef(I.getOperand(0).getReg()) - .addUse(LUiReg) + .addReg(LWGOTDef) .addGlobalAddress(GVal); - ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO); + ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO); + if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI)) + return false; + } + } else { + Register LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass); - if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI)) - return false; - if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI)) - return false; + MachineInstr *LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi)) + .addDef(LUiReg) + .addGlobalAddress(GVal); + LUi->getOperand(1).setTargetFlags(MipsII::MO_ABS_HI); + if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI)) + return false; + MachineInstr *ADDiu = + BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu)) + .addDef(I.getOperand(0).getReg()) + .addUse(LUiReg) + .addGlobalAddress(GVal); + ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO); + if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI)) + return false; + } I.eraseFromParent(); return true; } case G_ICMP: { struct Instr { - unsigned Opcode, Def, LHS, RHS; - Instr(unsigned Opcode, unsigned Def, unsigned LHS, unsigned RHS) + unsigned Opcode; + Register Def, LHS, RHS; + Instr(unsigned Opcode, Register Def, Register LHS, Register RHS) : Opcode(Opcode), Def(Def), LHS(LHS), RHS(RHS){}; bool hasImm() const { @@ -244,10 +511,10 @@ bool MipsInstructionSelector::select(MachineInstr &I, }; SmallVector<struct Instr, 2> Instructions; - unsigned ICMPReg = I.getOperand(0).getReg(); - unsigned Temp = MRI.createVirtualRegister(&Mips::GPR32RegClass); - unsigned LHS = I.getOperand(2).getReg(); - unsigned RHS = I.getOperand(3).getReg(); + Register ICMPReg = I.getOperand(0).getReg(); + Register Temp = MRI.createVirtualRegister(&Mips::GPR32RegClass); + Register LHS = I.getOperand(2).getReg(); + Register RHS = I.getOperand(3).getReg(); CmpInst::Predicate Cond = static_cast<CmpInst::Predicate>(I.getOperand(1).getPredicate()); @@ -309,6 +576,84 @@ bool MipsInstructionSelector::select(MachineInstr &I, I.eraseFromParent(); return true; } + case G_FCMP: { + unsigned MipsFCMPCondCode; + bool isLogicallyNegated; + switch (CmpInst::Predicate Cond = static_cast<CmpInst::Predicate>( + I.getOperand(1).getPredicate())) { + case CmpInst::FCMP_UNO: // Unordered + case CmpInst::FCMP_ORD: // Ordered (OR) + MipsFCMPCondCode = Mips::FCOND_UN; + isLogicallyNegated = Cond != CmpInst::FCMP_UNO; + break; + case CmpInst::FCMP_OEQ: // Equal + case CmpInst::FCMP_UNE: // Not Equal (NEQ) + MipsFCMPCondCode = Mips::FCOND_OEQ; + isLogicallyNegated = Cond != CmpInst::FCMP_OEQ; + break; + case CmpInst::FCMP_UEQ: // Unordered or Equal + case CmpInst::FCMP_ONE: // Ordered or Greater Than or Less Than (OGL) + MipsFCMPCondCode = Mips::FCOND_UEQ; + isLogicallyNegated = Cond != CmpInst::FCMP_UEQ; + break; + case CmpInst::FCMP_OLT: // Ordered or Less Than + case CmpInst::FCMP_UGE: // Unordered or Greater Than or Equal (UGE) + MipsFCMPCondCode = Mips::FCOND_OLT; + isLogicallyNegated = Cond != CmpInst::FCMP_OLT; + break; + case CmpInst::FCMP_ULT: // Unordered or Less Than + case CmpInst::FCMP_OGE: // Ordered or Greater Than or Equal (OGE) + MipsFCMPCondCode = Mips::FCOND_ULT; + isLogicallyNegated = Cond != CmpInst::FCMP_ULT; + break; + case CmpInst::FCMP_OLE: // Ordered or Less Than or Equal + case CmpInst::FCMP_UGT: // Unordered or Greater Than (UGT) + MipsFCMPCondCode = Mips::FCOND_OLE; + isLogicallyNegated = Cond != CmpInst::FCMP_OLE; + break; + case CmpInst::FCMP_ULE: // Unordered or Less Than or Equal + case CmpInst::FCMP_OGT: // Ordered or Greater Than (OGT) + MipsFCMPCondCode = Mips::FCOND_ULE; + isLogicallyNegated = Cond != CmpInst::FCMP_ULE; + break; + default: + return false; + } + + // Default compare result in gpr register will be `true`. + // We will move `false` (MIPS::Zero) to gpr result when fcmp gives false + // using MOVF_I. When orignal predicate (Cond) is logically negated + // MipsFCMPCondCode, result is inverted i.e. MOVT_I is used. + unsigned MoveOpcode = isLogicallyNegated ? Mips::MOVT_I : Mips::MOVF_I; + + unsigned TrueInReg = MRI.createVirtualRegister(&Mips::GPR32RegClass); + BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu)) + .addDef(TrueInReg) + .addUse(Mips::ZERO) + .addImm(1); + + unsigned Size = MRI.getType(I.getOperand(2).getReg()).getSizeInBits(); + unsigned FCMPOpcode = + Size == 32 ? Mips::FCMP_S32 + : STI.isFP64bit() ? Mips::FCMP_D64 : Mips::FCMP_D32; + MachineInstr *FCMP = BuildMI(MBB, I, I.getDebugLoc(), TII.get(FCMPOpcode)) + .addUse(I.getOperand(2).getReg()) + .addUse(I.getOperand(3).getReg()) + .addImm(MipsFCMPCondCode); + if (!constrainSelectedInstRegOperands(*FCMP, TII, TRI, RBI)) + return false; + + MachineInstr *Move = BuildMI(MBB, I, I.getDebugLoc(), TII.get(MoveOpcode)) + .addDef(I.getOperand(0).getReg()) + .addUse(Mips::ZERO) + .addUse(Mips::FCC0) + .addUse(TrueInReg); + if (!constrainSelectedInstRegOperands(*Move, TII, TRI, RBI)) + return false; + + I.eraseFromParent(); + return true; + } default: return false; } diff --git a/lib/Target/Mips/MipsLegalizerInfo.cpp b/lib/Target/Mips/MipsLegalizerInfo.cpp index c629f02af00e..e442a81837ed 100644 --- a/lib/Target/Mips/MipsLegalizerInfo.cpp +++ b/lib/Target/Mips/MipsLegalizerInfo.cpp @@ -1,9 +1,8 @@ //===- MipsLegalizerInfo.cpp ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// \file @@ -25,35 +24,65 @@ MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) { const LLT s64 = LLT::scalar(64); const LLT p0 = LLT::pointer(0, 32); - getActionDefinitionsBuilder(G_ADD) + getActionDefinitionsBuilder({G_ADD, G_SUB, G_MUL}) .legalFor({s32}) .clampScalar(0, s32, s32); - getActionDefinitionsBuilder(G_UADDE) + getActionDefinitionsBuilder({G_UADDO, G_UADDE, G_USUBO, G_USUBE, G_UMULO}) .lowerFor({{s32, s1}}); + getActionDefinitionsBuilder(G_UMULH) + .legalFor({s32}) + .maxScalar(0, s32); + getActionDefinitionsBuilder({G_LOAD, G_STORE}) - .legalForCartesianProduct({p0, s32}, {p0}); + .legalForTypesWithMemDesc({{s32, p0, 8, 8}, + {s32, p0, 16, 8}, + {s32, p0, 32, 8}, + {s64, p0, 64, 8}, + {p0, p0, 32, 8}}) + .minScalar(0, s32); + + getActionDefinitionsBuilder(G_UNMERGE_VALUES) + .legalFor({{s32, s64}}); + + getActionDefinitionsBuilder(G_MERGE_VALUES) + .legalFor({{s64, s32}}); + + getActionDefinitionsBuilder({G_ZEXTLOAD, G_SEXTLOAD}) + .legalForTypesWithMemDesc({{s32, p0, 8, 8}, + {s32, p0, 16, 8}}) + .minScalar(0, s32); getActionDefinitionsBuilder(G_SELECT) - .legalForCartesianProduct({p0, s32}, {s32}) + .legalForCartesianProduct({p0, s32, s64}, {s32}) .minScalar(0, s32) .minScalar(1, s32); + getActionDefinitionsBuilder(G_BRCOND) + .legalFor({s32}) + .minScalar(0, s32); + + getActionDefinitionsBuilder(G_PHI) + .legalFor({p0, s32, s64}) + .minScalar(0, s32); + getActionDefinitionsBuilder({G_AND, G_OR, G_XOR}) .legalFor({s32}) .clampScalar(0, s32, s32); - getActionDefinitionsBuilder({G_SHL, G_ASHR, G_LSHR}) - .legalFor({s32}); - getActionDefinitionsBuilder({G_SDIV, G_SREM, G_UREM, G_UDIV}) .legalFor({s32}) .minScalar(0, s32) .libcallFor({s64}); + getActionDefinitionsBuilder({G_SHL, G_ASHR, G_LSHR}) + .legalFor({s32, s32}) + .minScalar(1, s32); + getActionDefinitionsBuilder(G_ICMP) - .legalFor({{s32, s32}}) + .legalForCartesianProduct({s32}, {s32, p0}) + .clampScalar(1, s32, s32) .minScalar(0, s32); getActionDefinitionsBuilder(G_CONSTANT) @@ -69,6 +98,46 @@ MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) { getActionDefinitionsBuilder(G_GLOBAL_VALUE) .legalFor({p0}); + // FP instructions + getActionDefinitionsBuilder(G_FCONSTANT) + .legalFor({s32, s64}); + + getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FABS, G_FSQRT}) + .legalFor({s32, s64}); + + getActionDefinitionsBuilder(G_FCMP) + .legalFor({{s32, s32}, {s32, s64}}) + .minScalar(0, s32); + + getActionDefinitionsBuilder({G_FCEIL, G_FFLOOR}) + .libcallFor({s32, s64}); + + getActionDefinitionsBuilder(G_FPEXT) + .legalFor({{s64, s32}}); + + getActionDefinitionsBuilder(G_FPTRUNC) + .legalFor({{s32, s64}}); + + // FP to int conversion instructions + getActionDefinitionsBuilder(G_FPTOSI) + .legalForCartesianProduct({s32}, {s64, s32}) + .libcallForCartesianProduct({s64}, {s64, s32}) + .minScalar(0, s32); + + getActionDefinitionsBuilder(G_FPTOUI) + .libcallForCartesianProduct({s64}, {s64, s32}) + .minScalar(0, s32); + + // Int to FP conversion instructions + getActionDefinitionsBuilder(G_SITOFP) + .legalForCartesianProduct({s64, s32}, {s32}) + .libcallForCartesianProduct({s64, s32}, {s64}) + .minScalar(1, s32); + + getActionDefinitionsBuilder(G_UITOFP) + .libcallForCartesianProduct({s64, s32}, {s64}) + .minScalar(1, s32); + computeTables(); verify(*ST.getInstrInfo()); } diff --git a/lib/Target/Mips/MipsLegalizerInfo.h b/lib/Target/Mips/MipsLegalizerInfo.h index 75fadd6cf613..e5021e081890 100644 --- a/lib/Target/Mips/MipsLegalizerInfo.h +++ b/lib/Target/Mips/MipsLegalizerInfo.h @@ -1,9 +1,8 @@ //===- MipsLegalizerInfo ----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// \file diff --git a/lib/Target/Mips/MipsMCInstLower.cpp b/lib/Target/Mips/MipsMCInstLower.cpp index 46b37ceae391..fd984058a2bf 100644 --- a/lib/Target/Mips/MipsMCInstLower.cpp +++ b/lib/Target/Mips/MipsMCInstLower.cpp @@ -1,9 +1,8 @@ //===- MipsMCInstLower.cpp - Convert Mips MachineInstr to MCInst ----------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -117,6 +116,8 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO, case MipsII::MO_CALL_LO16: TargetKind = MipsMCExpr::MEK_CALL_LO16; break; + case MipsII::MO_JALR: + return MCOperand(); } switch (MOTy) { diff --git a/lib/Target/Mips/MipsMCInstLower.h b/lib/Target/Mips/MipsMCInstLower.h index e19f21c98839..29af6f21de82 100644 --- a/lib/Target/Mips/MipsMCInstLower.h +++ b/lib/Target/Mips/MipsMCInstLower.h @@ -1,9 +1,8 @@ //===- MipsMCInstLower.h - Lower MachineInstr to MCInst --------*- C++ -*--===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MipsMSAInstrFormats.td b/lib/Target/Mips/MipsMSAInstrFormats.td index d4e225678184..2bfc92c85e96 100644 --- a/lib/Target/Mips/MipsMSAInstrFormats.td +++ b/lib/Target/Mips/MipsMSAInstrFormats.td @@ -1,9 +1,8 @@ //===- MipsMSAInstrFormats.td - Mips Instruction Formats ---*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MipsMSAInstrInfo.td b/lib/Target/Mips/MipsMSAInstrInfo.td index eecc7c573df1..907ed9ef746f 100644 --- a/lib/Target/Mips/MipsMSAInstrInfo.td +++ b/lib/Target/Mips/MipsMSAInstrInfo.td @@ -1,9 +1,8 @@ //===- MipsMSAInstrInfo.td - MSA ASE instructions -*- tablegen ------------*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -1240,6 +1239,7 @@ class MSA_COPY_PSEUDO_BASE<SDPatternOperator OpNode, ValueType VecTy, MSAPseudo<(outs RCD:$wd), (ins RCWS:$ws, ImmOp:$n), [(set RCD:$wd, (OpNode (VecTy RCWS:$ws), Imm:$n))]> { bit usesCustomInserter = 1; + bit hasNoSchedulingInfo = 1; } class MSA_I5_DESC_BASE<string instr_asm, SDPatternOperator OpNode, @@ -1447,6 +1447,7 @@ class MSA_INSERT_VIDX_PSEUDO_BASE<SDPatternOperator OpNode, ValueType Ty, [(set ROWD:$wd, (OpNode (Ty ROWD:$wd_in), ROFS:$fs, ROIdx:$n))]> { bit usesCustomInserter = 1; + bit hasNoSchedulingInfo = 1; string Constraints = "$wd = $wd_in"; } @@ -2044,7 +2045,7 @@ class FEXDO_W_DESC : MSA_3RF_DESC_BASE<"fexdo.w", int_mips_fexdo_w, // 1.0 when we only need to match ISD::FEXP2. class FEXP2_W_DESC : MSA_3RF_DESC_BASE<"fexp2.w", mul_fexp2, MSA128WOpnd>; class FEXP2_D_DESC : MSA_3RF_DESC_BASE<"fexp2.d", mul_fexp2, MSA128DOpnd>; -let usesCustomInserter = 1 in { +let usesCustomInserter = 1, hasNoSchedulingInfo = 1 in { class FEXP2_W_1_PSEUDO_DESC : MSAPseudo<(outs MSA128W:$wd), (ins MSA128W:$ws), [(set MSA128W:$wd, (fexp2 MSA128W:$ws))]>; @@ -3738,6 +3739,7 @@ class MSA_CBRANCH_PSEUDO_DESC_BASE<SDPatternOperator OpNode, ValueType TyNode, (ins RCWS:$ws), [(set GPR32:$dst, (OpNode (TyNode RCWS:$ws)))]> { bit usesCustomInserter = 1; + bit hasNoSchedulingInfo = 1; } def SNZ_B_PSEUDO : MSA_CBRANCH_PSEUDO_DESC_BASE<MipsVAllNonZero, v16i8, @@ -3765,52 +3767,38 @@ def SZ_V_PSEUDO : MSA_CBRANCH_PSEUDO_DESC_BASE<MipsVAnyZero, v16i8, // Pseudoes used to implement transparent fp16 support. let ASEPredicate = [HasMSA] in { - def ST_F16 : MipsPseudo<(outs), (ins MSA128F16:$ws, mem_simm10:$addr), - [(store (f16 MSA128F16:$ws), (addrimm10:$addr))]> { - let usesCustomInserter = 1; - } - - def LD_F16 : MipsPseudo<(outs MSA128F16:$ws), (ins mem_simm10:$addr), - [(set MSA128F16:$ws, (f16 (load addrimm10:$addr)))]> { - let usesCustomInserter = 1; - } + let usesCustomInserter = 1 in { + def ST_F16 : + MipsPseudo<(outs), (ins MSA128F16:$ws, mem_simm10:$addr), + [(store (f16 MSA128F16:$ws), (addrimm10:$addr))]>; + def LD_F16 : + MipsPseudo<(outs MSA128F16:$ws), (ins mem_simm10:$addr), + [(set MSA128F16:$ws, (f16 (load addrimm10:$addr)))]>; + } - def MSA_FP_EXTEND_W_PSEUDO : MipsPseudo<(outs FGR32Opnd:$fd), - (ins MSA128F16:$ws), - [(set FGR32Opnd:$fd, - (f32 (fpextend MSA128F16:$ws)))]> { - let usesCustomInserter = 1; - } - - def MSA_FP_ROUND_W_PSEUDO : MipsPseudo<(outs MSA128F16:$wd), - (ins FGR32Opnd:$fs), - [(set MSA128F16:$wd, - (f16 (fpround FGR32Opnd:$fs)))]> { - let usesCustomInserter = 1; - } - - def MSA_FP_EXTEND_D_PSEUDO : MipsPseudo<(outs FGR64Opnd:$fd), - (ins MSA128F16:$ws), - [(set FGR64Opnd:$fd, - (f64 (fpextend MSA128F16:$ws)))]> { - let usesCustomInserter = 1; - } - - def MSA_FP_ROUND_D_PSEUDO : MipsPseudo<(outs MSA128F16:$wd), - (ins FGR64Opnd:$fs), - [(set MSA128F16:$wd, - (f16 (fpround FGR64Opnd:$fs)))]> { - let usesCustomInserter = 1; - } + let usesCustomInserter = 1, hasNoSchedulingInfo = 1 in { + def MSA_FP_EXTEND_W_PSEUDO : + MipsPseudo<(outs FGR32Opnd:$fd), (ins MSA128F16:$ws), + [(set FGR32Opnd:$fd, (f32 (fpextend MSA128F16:$ws)))]>; + def MSA_FP_ROUND_W_PSEUDO : + MipsPseudo<(outs MSA128F16:$wd), (ins FGR32Opnd:$fs), + [(set MSA128F16:$wd, (f16 (fpround FGR32Opnd:$fs)))]>; + def MSA_FP_EXTEND_D_PSEUDO : + MipsPseudo<(outs FGR64Opnd:$fd), (ins MSA128F16:$ws), + [(set FGR64Opnd:$fd, (f64 (fpextend MSA128F16:$ws)))]>; + def MSA_FP_ROUND_D_PSEUDO : + MipsPseudo<(outs MSA128F16:$wd), (ins FGR64Opnd:$fs), + [(set MSA128F16:$wd, (f16 (fpround FGR64Opnd:$fs)))]>; + } - def : MipsPat<(MipsTruncIntFP MSA128F16:$ws), - (TRUNC_W_D64 (MSA_FP_EXTEND_D_PSEUDO MSA128F16:$ws))>, ISA_MIPS1, - ASE_MSA; + def : MipsPat<(MipsTruncIntFP MSA128F16:$ws), + (TRUNC_W_D64 (MSA_FP_EXTEND_D_PSEUDO MSA128F16:$ws))>, + ISA_MIPS1, ASE_MSA; - def : MipsPat<(MipsFPCmp MSA128F16:$ws, MSA128F16:$wt, imm:$cond), - (FCMP_S32 (MSA_FP_EXTEND_W_PSEUDO MSA128F16:$ws), - (MSA_FP_EXTEND_W_PSEUDO MSA128F16:$wt), imm:$cond)>, - ISA_MIPS1_NOT_32R6_64R6, ASE_MSA; + def : MipsPat<(MipsFPCmp MSA128F16:$ws, MSA128F16:$wt, imm:$cond), + (FCMP_S32 (MSA_FP_EXTEND_W_PSEUDO MSA128F16:$ws), + (MSA_FP_EXTEND_W_PSEUDO MSA128F16:$wt), imm:$cond)>, + ISA_MIPS1_NOT_32R6_64R6, ASE_MSA; } def vsplati64_imm_eq_63 : PatLeaf<(bitconvert (v4i32 (build_vector))), [{ diff --git a/lib/Target/Mips/MipsMTInstrFormats.td b/lib/Target/Mips/MipsMTInstrFormats.td index c2c22e2ad61c..22c290b1c114 100644 --- a/lib/Target/Mips/MipsMTInstrFormats.td +++ b/lib/Target/Mips/MipsMTInstrFormats.td @@ -1,9 +1,8 @@ //===-- MipsMTInstrFormats.td - Mips Instruction Formats ---*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MipsMTInstrInfo.td b/lib/Target/Mips/MipsMTInstrInfo.td index 72e626cbec40..3edeb57b1876 100644 --- a/lib/Target/Mips/MipsMTInstrInfo.td +++ b/lib/Target/Mips/MipsMTInstrInfo.td @@ -1,9 +1,8 @@ //===-- MipsMTInstrInfo.td - Mips MT Instruction Infos -----*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/MipsMachineFunction.cpp b/lib/Target/Mips/MipsMachineFunction.cpp index 81b4352670c0..85b20fc58231 100644 --- a/lib/Target/Mips/MipsMachineFunction.cpp +++ b/lib/Target/Mips/MipsMachineFunction.cpp @@ -1,9 +1,8 @@ //===-- MipsMachineFunctionInfo.cpp - Private data used for Mips ----------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -45,13 +44,109 @@ static const TargetRegisterClass &getGlobalBaseRegClass(MachineFunction &MF) { return Mips::GPR32RegClass; } -unsigned MipsFunctionInfo::getGlobalBaseReg() { +Register MipsFunctionInfo::getGlobalBaseReg() { if (!GlobalBaseReg) GlobalBaseReg = MF.getRegInfo().createVirtualRegister(&getGlobalBaseRegClass(MF)); return GlobalBaseReg; } +Register MipsFunctionInfo::getGlobalBaseRegForGlobalISel() { + if (!GlobalBaseReg) { + getGlobalBaseReg(); + initGlobalBaseReg(); + } + return GlobalBaseReg; +} + +void MipsFunctionInfo::initGlobalBaseReg() { + if (!GlobalBaseReg) + return; + + MachineBasicBlock &MBB = MF.front(); + MachineBasicBlock::iterator I = MBB.begin(); + MachineRegisterInfo &RegInfo = MF.getRegInfo(); + const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); + DebugLoc DL; + unsigned V0, V1; + const TargetRegisterClass *RC; + const MipsABIInfo &ABI = + static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI(); + RC = (ABI.IsN64()) ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; + + V0 = RegInfo.createVirtualRegister(RC); + V1 = RegInfo.createVirtualRegister(RC); + + if (ABI.IsN64()) { + MF.getRegInfo().addLiveIn(Mips::T9_64); + MBB.addLiveIn(Mips::T9_64); + + // lui $v0, %hi(%neg(%gp_rel(fname))) + // daddu $v1, $v0, $t9 + // daddiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname))) + const GlobalValue *FName = &MF.getFunction(); + BuildMI(MBB, I, DL, TII.get(Mips::LUi64), V0) + .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI); + BuildMI(MBB, I, DL, TII.get(Mips::DADDu), V1).addReg(V0) + .addReg(Mips::T9_64); + BuildMI(MBB, I, DL, TII.get(Mips::DADDiu), GlobalBaseReg).addReg(V1) + .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO); + return; + } + + if (!MF.getTarget().isPositionIndependent()) { + // Set global register to __gnu_local_gp. + // + // lui $v0, %hi(__gnu_local_gp) + // addiu $globalbasereg, $v0, %lo(__gnu_local_gp) + BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0) + .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_HI); + BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V0) + .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_LO); + return; + } + + MF.getRegInfo().addLiveIn(Mips::T9); + MBB.addLiveIn(Mips::T9); + + if (ABI.IsN32()) { + // lui $v0, %hi(%neg(%gp_rel(fname))) + // addu $v1, $v0, $t9 + // addiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname))) + const GlobalValue *FName = &MF.getFunction(); + BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0) + .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI); + BuildMI(MBB, I, DL, TII.get(Mips::ADDu), V1).addReg(V0).addReg(Mips::T9); + BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V1) + .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO); + return; + } + + assert(ABI.IsO32()); + + // For O32 ABI, the following instruction sequence is emitted to initialize + // the global base register: + // + // 0. lui $2, %hi(_gp_disp) + // 1. addiu $2, $2, %lo(_gp_disp) + // 2. addu $globalbasereg, $2, $t9 + // + // We emit only the last instruction here. + // + // GNU linker requires that the first two instructions appear at the beginning + // of a function and no instructions be inserted before or between them. + // The two instructions are emitted during lowering to MC layer in order to + // avoid any reordering. + // + // Register $2 (Mips::V0) is added to the list of live-in registers to ensure + // the value instruction 1 (addiu) defines is valid when instruction 2 (addu) + // reads it. + MF.getRegInfo().addLiveIn(Mips::V0); + MBB.addLiveIn(Mips::V0); + BuildMI(MBB, I, DL, TII.get(Mips::ADDu), GlobalBaseReg) + .addReg(Mips::V0).addReg(Mips::T9); +} + void MipsFunctionInfo::createEhDataRegsFI() { const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); for (int I = 0; I < 4; ++I) { diff --git a/lib/Target/Mips/MipsMachineFunction.h b/lib/Target/Mips/MipsMachineFunction.h index 553a66703b26..aaa1e0e18441 100644 --- a/lib/Target/Mips/MipsMachineFunction.h +++ b/lib/Target/Mips/MipsMachineFunction.h @@ -1,9 +1,8 @@ //===- MipsMachineFunctionInfo.h - Private data used for Mips ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -33,7 +32,12 @@ public: void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; } bool globalBaseRegSet() const; - unsigned getGlobalBaseReg(); + Register getGlobalBaseReg(); + Register getGlobalBaseRegForGlobalISel(); + + // Insert instructions to initialize the global base register in the + // first MBB of the function. + void initGlobalBaseReg(); int getVarArgsFrameIndex() const { return VarArgsFrameIndex; } void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; } diff --git a/lib/Target/Mips/MipsOptimizePICCall.cpp b/lib/Target/Mips/MipsOptimizePICCall.cpp index 27bc4843f410..5ef07a2d283e 100644 --- a/lib/Target/Mips/MipsOptimizePICCall.cpp +++ b/lib/Target/Mips/MipsOptimizePICCall.cpp @@ -1,9 +1,8 @@ //===- MipsOptimizePICCall.cpp - Optimize PIC Calls -----------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/MipsOptionRecord.h b/lib/Target/Mips/MipsOptionRecord.h index 4708784063d3..7897095ef894 100644 --- a/lib/Target/Mips/MipsOptionRecord.h +++ b/lib/Target/Mips/MipsOptionRecord.h @@ -1,9 +1,8 @@ //===- MipsOptionRecord.h - Abstraction for storing information -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/MipsOs16.cpp b/lib/Target/Mips/MipsOs16.cpp index 4edcb3132ada..ac4e55f8a1f5 100644 --- a/lib/Target/Mips/MipsOs16.cpp +++ b/lib/Target/Mips/MipsOs16.cpp @@ -1,9 +1,8 @@ //===---- MipsOs16.cpp for Mips Option -Os16 --------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/MipsPreLegalizerCombiner.cpp b/lib/Target/Mips/MipsPreLegalizerCombiner.cpp index 1cff1c8396ea..85076590d407 100644 --- a/lib/Target/Mips/MipsPreLegalizerCombiner.cpp +++ b/lib/Target/Mips/MipsPreLegalizerCombiner.cpp @@ -1,9 +1,8 @@ //=== lib/CodeGen/GlobalISel/MipsPreLegalizerCombiner.cpp --------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -14,6 +13,7 @@ #include "MipsTargetMachine.h" #include "llvm/CodeGen/GlobalISel/Combiner.h" +#include "llvm/CodeGen/GlobalISel/CombinerHelper.h" #include "llvm/CodeGen/GlobalISel/CombinerInfo.h" #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h" #include "llvm/CodeGen/TargetPassConfig.h" @@ -35,6 +35,16 @@ public: bool MipsPreLegalizerCombinerInfo::combine(GISelChangeObserver &Observer, MachineInstr &MI, MachineIRBuilder &B) const { + CombinerHelper Helper(Observer, B); + + switch (MI.getOpcode()) { + default: + return false; + case TargetOpcode::G_LOAD: + case TargetOpcode::G_SEXTLOAD: + case TargetOpcode::G_ZEXTLOAD: + return Helper.tryCombineExtendingLoads(MI); + } return false; } diff --git a/lib/Target/Mips/MipsRegisterBankInfo.cpp b/lib/Target/Mips/MipsRegisterBankInfo.cpp index 6af1f10189df..d8bcf16afd50 100644 --- a/lib/Target/Mips/MipsRegisterBankInfo.cpp +++ b/lib/Target/Mips/MipsRegisterBankInfo.cpp @@ -1,9 +1,8 @@ //===- MipsRegisterBankInfo.cpp ---------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// \file @@ -11,36 +10,55 @@ /// \todo This should be generated by TableGen. //===----------------------------------------------------------------------===// -#include "MipsInstrInfo.h" #include "MipsRegisterBankInfo.h" +#include "MipsInstrInfo.h" +#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" +#include "llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h" +#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #define GET_TARGET_REGBANK_IMPL -#define DEBUG_TYPE "registerbankinfo" - #include "MipsGenRegisterBank.inc" namespace llvm { namespace Mips { enum PartialMappingIdx { PMI_GPR, + PMI_SPR, + PMI_DPR, PMI_Min = PMI_GPR, }; RegisterBankInfo::PartialMapping PartMappings[]{ - {0, 32, GPRBRegBank} + {0, 32, GPRBRegBank}, + {0, 32, FPRBRegBank}, + {0, 64, FPRBRegBank} }; -enum ValueMappingIdx { InvalidIdx = 0, GPRIdx = 1 }; +enum ValueMappingIdx { + InvalidIdx = 0, + GPRIdx = 1, + SPRIdx = 4, + DPRIdx = 7 +}; RegisterBankInfo::ValueMapping ValueMappings[] = { // invalid {nullptr, 0}, - // 3 operands in GPRs + // up to 3 operands in GPRs {&PartMappings[PMI_GPR - PMI_Min], 1}, {&PartMappings[PMI_GPR - PMI_Min], 1}, - {&PartMappings[PMI_GPR - PMI_Min], 1}}; + {&PartMappings[PMI_GPR - PMI_Min], 1}, + // up to 3 ops operands FPRs - single precission + {&PartMappings[PMI_SPR - PMI_Min], 1}, + {&PartMappings[PMI_SPR - PMI_Min], 1}, + {&PartMappings[PMI_SPR - PMI_Min], 1}, + // up to 3 ops operands FPRs - double precission + {&PartMappings[PMI_DPR - PMI_Min], 1}, + {&PartMappings[PMI_DPR - PMI_Min], 1}, + {&PartMappings[PMI_DPR - PMI_Min], 1} +}; } // end namespace Mips } // end namespace llvm @@ -62,30 +80,313 @@ const RegisterBank &MipsRegisterBankInfo::getRegBankFromRegClass( case Mips::GPRMM16MoveP_and_CPU16Regs_and_GPRMM16ZeroRegClassID: case Mips::GPRMM16MovePPairFirst_and_GPRMM16MovePPairSecondRegClassID: case Mips::SP32RegClassID: + case Mips::GP32RegClassID: return getRegBank(Mips::GPRBRegBankID); + case Mips::FGRCCRegClassID: + case Mips::FGR32RegClassID: + case Mips::FGR64RegClassID: + case Mips::AFGR64RegClassID: + return getRegBank(Mips::FPRBRegBankID); default: llvm_unreachable("Register class not supported"); } } +// Instructions where all register operands are floating point. +static bool isFloatingPointOpcode(unsigned Opc) { + switch (Opc) { + case TargetOpcode::G_FCONSTANT: + case TargetOpcode::G_FADD: + case TargetOpcode::G_FSUB: + case TargetOpcode::G_FMUL: + case TargetOpcode::G_FDIV: + case TargetOpcode::G_FABS: + case TargetOpcode::G_FSQRT: + case TargetOpcode::G_FCEIL: + case TargetOpcode::G_FFLOOR: + case TargetOpcode::G_FPEXT: + case TargetOpcode::G_FPTRUNC: + return true; + default: + return false; + } +} + +// Instructions where use operands are floating point registers. +// Def operands are general purpose. +static bool isFloatingPointOpcodeUse(unsigned Opc) { + switch (Opc) { + case TargetOpcode::G_FPTOSI: + case TargetOpcode::G_FPTOUI: + case TargetOpcode::G_FCMP: + case Mips::MFC1: + case Mips::ExtractElementF64: + case Mips::ExtractElementF64_64: + return true; + default: + return isFloatingPointOpcode(Opc); + } +} + +// Instructions where def operands are floating point registers. +// Use operands are general purpose. +static bool isFloatingPointOpcodeDef(unsigned Opc) { + switch (Opc) { + case TargetOpcode::G_SITOFP: + case TargetOpcode::G_UITOFP: + case Mips::MTC1: + case Mips::BuildPairF64: + case Mips::BuildPairF64_64: + return true; + default: + return isFloatingPointOpcode(Opc); + } +} + +static bool isAmbiguous(unsigned Opc) { + switch (Opc) { + case TargetOpcode::G_LOAD: + case TargetOpcode::G_STORE: + case TargetOpcode::G_PHI: + case TargetOpcode::G_SELECT: + return true; + default: + return false; + } +} + +void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addDefUses( + Register Reg, const MachineRegisterInfo &MRI) { + assert(!MRI.getType(Reg).isPointer() && + "Pointers are gprb, they should not be considered as ambiguous.\n"); + for (MachineInstr &UseMI : MRI.use_instructions(Reg)) { + MachineInstr *NonCopyInstr = skipCopiesOutgoing(&UseMI); + // Copy with many uses. + if (NonCopyInstr->getOpcode() == TargetOpcode::COPY && + !TargetRegisterInfo::isPhysicalRegister( + NonCopyInstr->getOperand(0).getReg())) + addDefUses(NonCopyInstr->getOperand(0).getReg(), MRI); + else + DefUses.push_back(skipCopiesOutgoing(&UseMI)); + } +} + +void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addUseDef( + Register Reg, const MachineRegisterInfo &MRI) { + assert(!MRI.getType(Reg).isPointer() && + "Pointers are gprb, they should not be considered as ambiguous.\n"); + MachineInstr *DefMI = MRI.getVRegDef(Reg); + UseDefs.push_back(skipCopiesIncoming(DefMI)); +} + +MachineInstr * +MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesOutgoing( + MachineInstr *MI) const { + const MachineFunction &MF = *MI->getParent()->getParent(); + const MachineRegisterInfo &MRI = MF.getRegInfo(); + MachineInstr *Ret = MI; + while (Ret->getOpcode() == TargetOpcode::COPY && + !TargetRegisterInfo::isPhysicalRegister(Ret->getOperand(0).getReg()) && + MRI.hasOneUse(Ret->getOperand(0).getReg())) { + Ret = &(*MRI.use_instr_begin(Ret->getOperand(0).getReg())); + } + return Ret; +} + +MachineInstr * +MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesIncoming( + MachineInstr *MI) const { + const MachineFunction &MF = *MI->getParent()->getParent(); + const MachineRegisterInfo &MRI = MF.getRegInfo(); + MachineInstr *Ret = MI; + while (Ret->getOpcode() == TargetOpcode::COPY && + !TargetRegisterInfo::isPhysicalRegister(Ret->getOperand(1).getReg())) + Ret = MRI.getVRegDef(Ret->getOperand(1).getReg()); + return Ret; +} + +MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer( + const MachineInstr *MI) { + assert(isAmbiguous(MI->getOpcode()) && + "Not implemented for non Ambiguous opcode.\n"); + + const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo(); + + if (MI->getOpcode() == TargetOpcode::G_LOAD) + addDefUses(MI->getOperand(0).getReg(), MRI); + + if (MI->getOpcode() == TargetOpcode::G_STORE) + addUseDef(MI->getOperand(0).getReg(), MRI); + + if (MI->getOpcode() == TargetOpcode::G_PHI) { + addDefUses(MI->getOperand(0).getReg(), MRI); + + for (unsigned i = 1; i < MI->getNumOperands(); i += 2) + addUseDef(MI->getOperand(i).getReg(), MRI); + } + + if (MI->getOpcode() == TargetOpcode::G_SELECT) { + addDefUses(MI->getOperand(0).getReg(), MRI); + + addUseDef(MI->getOperand(2).getReg(), MRI); + addUseDef(MI->getOperand(3).getReg(), MRI); + } +} + +bool MipsRegisterBankInfo::TypeInfoForMF::visit( + const MachineInstr *MI, const MachineInstr *WaitingForTypeOfMI) { + assert(isAmbiguous(MI->getOpcode()) && "Visiting non-Ambiguous opcode.\n"); + if (wasVisited(MI)) + return true; // InstType has already been determined for MI. + + startVisit(MI); + AmbiguousRegDefUseContainer DefUseContainer(MI); + + // Visit instructions where MI's DEF operands are USED. + if (visitAdjacentInstrs(MI, DefUseContainer.getDefUses(), true)) + return true; + + // Visit instructions that DEFINE MI's USE operands. + if (visitAdjacentInstrs(MI, DefUseContainer.getUseDefs(), false)) + return true; + + // All MI's adjacent instructions, are ambiguous. + if (!WaitingForTypeOfMI) { + // This is chain of ambiguous instructions. + setTypes(MI, InstType::Ambiguous); + return true; + } + // Excluding WaitingForTypeOfMI, MI is either connected to chains of ambiguous + // instructions or has no other adjacent instructions. Anyway InstType could + // not be determined. There could be unexplored path from some of + // WaitingForTypeOfMI's adjacent instructions to an instruction with only one + // mapping available. + // We are done with this branch, add MI to WaitingForTypeOfMI's WaitingQueue, + // this way when WaitingForTypeOfMI figures out its InstType same InstType + // will be assigned to all instructions in this branch. + addToWaitingQueue(WaitingForTypeOfMI, MI); + return false; +} + +bool MipsRegisterBankInfo::TypeInfoForMF::visitAdjacentInstrs( + const MachineInstr *MI, SmallVectorImpl<MachineInstr *> &AdjacentInstrs, + bool isDefUse) { + while (!AdjacentInstrs.empty()) { + MachineInstr *AdjMI = AdjacentInstrs.pop_back_val(); + + if (isDefUse ? isFloatingPointOpcodeUse(AdjMI->getOpcode()) + : isFloatingPointOpcodeDef(AdjMI->getOpcode())) { + setTypes(MI, InstType::FloatingPoint); + return true; + } + + // Determine InstType from register bank of phys register that is + // 'isDefUse ? def : use' of this copy. + if (AdjMI->getOpcode() == TargetOpcode::COPY) { + setTypesAccordingToPhysicalRegister(MI, AdjMI, isDefUse ? 0 : 1); + return true; + } + + // Defaults to integer instruction. Includes G_MERGE_VALUES and + // G_UNMERGE_VALUES. + if (!isAmbiguous(AdjMI->getOpcode())) { + setTypes(MI, InstType::Integer); + return true; + } + + // When AdjMI was visited first, MI has to continue to explore remaining + // adjacent instructions and determine InstType without visiting AdjMI. + if (!wasVisited(AdjMI) || + getRecordedTypeForInstr(AdjMI) != InstType::NotDetermined) { + if (visit(AdjMI, MI)) { + // InstType is successfully determined and is same as for AdjMI. + setTypes(MI, getRecordedTypeForInstr(AdjMI)); + return true; + } + } + } + return false; +} + +void MipsRegisterBankInfo::TypeInfoForMF::setTypes(const MachineInstr *MI, + InstType InstTy) { + changeRecordedTypeForInstr(MI, InstTy); + for (const MachineInstr *WaitingInstr : getWaitingQueueFor(MI)) { + setTypes(WaitingInstr, InstTy); + } +} + +void MipsRegisterBankInfo::TypeInfoForMF::setTypesAccordingToPhysicalRegister( + const MachineInstr *MI, const MachineInstr *CopyInst, unsigned Op) { + assert((TargetRegisterInfo::isPhysicalRegister( + CopyInst->getOperand(Op).getReg())) && + "Copies of non physical registers should not be considered here.\n"); + + const MachineFunction &MF = *CopyInst->getMF(); + const MachineRegisterInfo &MRI = MF.getRegInfo(); + const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); + const RegisterBankInfo &RBI = + *CopyInst->getMF()->getSubtarget().getRegBankInfo(); + const RegisterBank *Bank = + RBI.getRegBank(CopyInst->getOperand(Op).getReg(), MRI, TRI); + + if (Bank == &Mips::FPRBRegBank) + setTypes(MI, InstType::FloatingPoint); + else if (Bank == &Mips::GPRBRegBank) + setTypes(MI, InstType::Integer); + else + llvm_unreachable("Unsupported register bank.\n"); +} + +MipsRegisterBankInfo::InstType +MipsRegisterBankInfo::TypeInfoForMF::determineInstType(const MachineInstr *MI) { + visit(MI, nullptr); + return getRecordedTypeForInstr(MI); +} + +void MipsRegisterBankInfo::TypeInfoForMF::cleanupIfNewFunction( + llvm::StringRef FunctionName) { + if (MFName != FunctionName) { + MFName = FunctionName; + WaitingQueues.clear(); + Types.clear(); + } +} + const RegisterBankInfo::InstructionMapping & MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { + static TypeInfoForMF TI; + + // Reset TI internal data when MF changes. + TI.cleanupIfNewFunction(MI.getMF()->getName()); + unsigned Opc = MI.getOpcode(); + const MachineFunction &MF = *MI.getParent()->getParent(); + const MachineRegisterInfo &MRI = MF.getRegInfo(); - const RegisterBankInfo::InstructionMapping &Mapping = getInstrMappingImpl(MI); - if (Mapping.isValid()) - return Mapping; + if (MI.getOpcode() != TargetOpcode::G_PHI) { + const RegisterBankInfo::InstructionMapping &Mapping = + getInstrMappingImpl(MI); + if (Mapping.isValid()) + return Mapping; + } using namespace TargetOpcode; unsigned NumOperands = MI.getNumOperands(); const ValueMapping *OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx]; + unsigned MappingID = DefaultMappingID; + const unsigned CustomMappingID = 1; switch (Opc) { + case G_TRUNC: case G_ADD: - case G_LOAD: - case G_STORE: + case G_SUB: + case G_MUL: + case G_UMULH: + case G_ZEXTLOAD: + case G_SEXTLOAD: case G_GEP: case G_AND: case G_OR: @@ -99,9 +400,183 @@ MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { case G_UREM: OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx]; break; + case G_LOAD: { + unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); + InstType InstTy = InstType::Integer; + if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) { + InstTy = TI.determineInstType(&MI); + } + + if (InstTy == InstType::FloatingPoint || + (Size == 64 && InstTy == InstType::Ambiguous)) { // fprb + OperandsMapping = + getOperandsMapping({Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx] + : &Mips::ValueMappings[Mips::DPRIdx], + &Mips::ValueMappings[Mips::GPRIdx]}); + break; + } else { // gprb + OperandsMapping = + getOperandsMapping({Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx] + : &Mips::ValueMappings[Mips::DPRIdx], + &Mips::ValueMappings[Mips::GPRIdx]}); + if (Size == 64) + MappingID = CustomMappingID; + } + + break; + } + case G_STORE: { + unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); + InstType InstTy = InstType::Integer; + if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) { + InstTy = TI.determineInstType(&MI); + } + + if (InstTy == InstType::FloatingPoint || + (Size == 64 && InstTy == InstType::Ambiguous)) { // fprb + OperandsMapping = + getOperandsMapping({Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx] + : &Mips::ValueMappings[Mips::DPRIdx], + &Mips::ValueMappings[Mips::GPRIdx]}); + break; + } else { // gprb + OperandsMapping = + getOperandsMapping({Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx] + : &Mips::ValueMappings[Mips::DPRIdx], + &Mips::ValueMappings[Mips::GPRIdx]}); + if (Size == 64) + MappingID = CustomMappingID; + } + break; + } + case G_PHI: { + unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); + InstType InstTy = InstType::Integer; + if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) { + InstTy = TI.determineInstType(&MI); + } + + // PHI is copylike and should have one regbank in mapping for def register. + if (InstTy == InstType::Integer && Size == 64) { // fprb + OperandsMapping = + getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx]}); + return getInstructionMapping(CustomMappingID, /*Cost=*/1, OperandsMapping, + /*NumOperands=*/1); + } + // Use default handling for PHI, i.e. set reg bank of def operand to match + // register banks of use operands. + const RegisterBankInfo::InstructionMapping &Mapping = + getInstrMappingImpl(MI); + return Mapping; + } + case G_SELECT: { + unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); + InstType InstTy = InstType::Integer; + if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) { + InstTy = TI.determineInstType(&MI); + } + + if (InstTy == InstType::FloatingPoint || + (Size == 64 && InstTy == InstType::Ambiguous)) { // fprb + const RegisterBankInfo::ValueMapping *Bank = + Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx] + : &Mips::ValueMappings[Mips::DPRIdx]; + OperandsMapping = getOperandsMapping( + {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank}); + break; + } else { // gprb + const RegisterBankInfo::ValueMapping *Bank = + Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx] + : &Mips::ValueMappings[Mips::DPRIdx]; + OperandsMapping = getOperandsMapping( + {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank}); + if (Size == 64) + MappingID = CustomMappingID; + } + break; + } + case G_UNMERGE_VALUES: { + OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], + &Mips::ValueMappings[Mips::GPRIdx], + &Mips::ValueMappings[Mips::DPRIdx]}); + MappingID = CustomMappingID; + break; + } + case G_MERGE_VALUES: { + OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx], + &Mips::ValueMappings[Mips::GPRIdx], + &Mips::ValueMappings[Mips::GPRIdx]}); + MappingID = CustomMappingID; + break; + } + case G_FADD: + case G_FSUB: + case G_FMUL: + case G_FDIV: + case G_FABS: + case G_FSQRT:{ + unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); + assert((Size == 32 || Size == 64) && "Unsupported floating point size"); + OperandsMapping = Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx] + : &Mips::ValueMappings[Mips::DPRIdx]; + break; + } + case G_FCONSTANT: { + unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); + assert((Size == 32 || Size == 64) && "Unsupported floating point size"); + const RegisterBankInfo::ValueMapping *FPRValueMapping = + Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx] + : &Mips::ValueMappings[Mips::DPRIdx]; + OperandsMapping = getOperandsMapping({FPRValueMapping, nullptr}); + break; + } + case G_FCMP: { + unsigned Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits(); + assert((Size == 32 || Size == 64) && "Unsupported floating point size"); + const RegisterBankInfo::ValueMapping *FPRValueMapping = + Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx] + : &Mips::ValueMappings[Mips::DPRIdx]; + OperandsMapping = + getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr, + FPRValueMapping, FPRValueMapping}); + break; + } + case G_FPEXT: + OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx], + &Mips::ValueMappings[Mips::SPRIdx]}); + break; + case G_FPTRUNC: + OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::SPRIdx], + &Mips::ValueMappings[Mips::DPRIdx]}); + break; + case G_FPTOSI: { + unsigned SizeFP = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); + assert((MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() == 32) && + "Unsupported integer size"); + assert((SizeFP == 32 || SizeFP == 64) && "Unsupported floating point size"); + OperandsMapping = getOperandsMapping({ + &Mips::ValueMappings[Mips::GPRIdx], + SizeFP == 32 ? &Mips::ValueMappings[Mips::SPRIdx] + : &Mips::ValueMappings[Mips::DPRIdx], + }); + break; + } + case G_SITOFP: { + unsigned SizeInt = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); + unsigned SizeFP = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); + (void)SizeInt; + assert((SizeInt == 32) && "Unsupported integer size"); + assert((SizeFP == 32 || SizeFP == 64) && "Unsupported floating point size"); + OperandsMapping = + getOperandsMapping({SizeFP == 32 ? &Mips::ValueMappings[Mips::SPRIdx] + : &Mips::ValueMappings[Mips::DPRIdx], + &Mips::ValueMappings[Mips::GPRIdx]}); + break; + } case G_CONSTANT: case G_FRAME_INDEX: case G_GLOBAL_VALUE: + case G_BRCOND: OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr}); break; @@ -111,17 +586,92 @@ MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { &Mips::ValueMappings[Mips::GPRIdx], &Mips::ValueMappings[Mips::GPRIdx]}); break; - case G_SELECT: - OperandsMapping = - getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], - &Mips::ValueMappings[Mips::GPRIdx], - &Mips::ValueMappings[Mips::GPRIdx], - &Mips::ValueMappings[Mips::GPRIdx]}); - break; default: return getInvalidInstructionMapping(); } - return getInstructionMapping(DefaultMappingID, /*Cost=*/1, OperandsMapping, + return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping, NumOperands); } + +using InstListTy = GISelWorkList<4>; +namespace { +class InstManager : public GISelChangeObserver { + InstListTy &InstList; + +public: + InstManager(InstListTy &Insts) : InstList(Insts) {} + + void createdInstr(MachineInstr &MI) override { InstList.insert(&MI); } + void erasingInstr(MachineInstr &MI) override {} + void changingInstr(MachineInstr &MI) override {} + void changedInstr(MachineInstr &MI) override {} +}; +} // end anonymous namespace + +/// Here we have to narrowScalar s64 operands to s32, combine away +/// G_MERGE/G_UNMERGE and erase instructions that became dead in the process. +/// We manually assign 32 bit gprb to register operands of all new instructions +/// that got created in the process since they will not end up in RegBankSelect +/// loop. Careful not to delete instruction after MI i.e. MI.getIterator()++. +void MipsRegisterBankInfo::applyMappingImpl( + const OperandsMapper &OpdMapper) const { + MachineInstr &MI = OpdMapper.getMI(); + InstListTy NewInstrs; + MachineIRBuilder B(MI); + MachineFunction *MF = MI.getMF(); + MachineRegisterInfo &MRI = OpdMapper.getMRI(); + + InstManager NewInstrObserver(NewInstrs); + GISelObserverWrapper WrapperObserver(&NewInstrObserver); + LegalizerHelper Helper(*MF, WrapperObserver, B); + LegalizationArtifactCombiner ArtCombiner( + B, MF->getRegInfo(), *MF->getSubtarget().getLegalizerInfo()); + + switch (MI.getOpcode()) { + case TargetOpcode::G_LOAD: + case TargetOpcode::G_STORE: + case TargetOpcode::G_PHI: + case TargetOpcode::G_SELECT: { + Helper.narrowScalar(MI, 0, LLT::scalar(32)); + // Handle new instructions. + while (!NewInstrs.empty()) { + MachineInstr *NewMI = NewInstrs.pop_back_val(); + // This is new G_UNMERGE that was created during narrowScalar and will + // not be considered for regbank selection. RegBankSelect for mips + // visits/makes corresponding G_MERGE first. Combine them here. + if (NewMI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) { + SmallVector<MachineInstr *, 2> DeadInstrs; + ArtCombiner.tryCombineMerges(*NewMI, DeadInstrs); + for (MachineInstr *DeadMI : DeadInstrs) + DeadMI->eraseFromParent(); + } + // This G_MERGE will be combined away when its corresponding G_UNMERGE + // gets regBankSelected. + else if (NewMI->getOpcode() == TargetOpcode::G_MERGE_VALUES) + continue; + else + // Manually set register banks for all register operands to 32 bit gprb. + for (auto Op : NewMI->operands()) { + if (Op.isReg()) { + assert(MRI.getType(Op.getReg()).getSizeInBits() == 32 && + "Only 32 bit gprb is handled here.\n"); + MRI.setRegBank(Op.getReg(), getRegBank(Mips::GPRBRegBankID)); + } + } + } + return; + } + case TargetOpcode::G_UNMERGE_VALUES: { + SmallVector<MachineInstr *, 2> DeadInstrs; + ArtCombiner.tryCombineMerges(MI, DeadInstrs); + for (MachineInstr *DeadMI : DeadInstrs) + DeadMI->eraseFromParent(); + return; + } + default: + break; + } + + return applyDefaultMapping(OpdMapper); +} diff --git a/lib/Target/Mips/MipsRegisterBankInfo.h b/lib/Target/Mips/MipsRegisterBankInfo.h index 64a79abaa74d..176813c031ed 100644 --- a/lib/Target/Mips/MipsRegisterBankInfo.h +++ b/lib/Target/Mips/MipsRegisterBankInfo.h @@ -1,9 +1,8 @@ //===- MipsRegisterBankInfo.h -----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// \file @@ -38,6 +37,131 @@ public: const InstructionMapping & getInstrMapping(const MachineInstr &MI) const override; + + void applyMappingImpl(const OperandsMapper &OpdMapper) const override; + +private: + /// Some instructions are used with both floating point and integer operands. + /// We assign InstType to such instructions as it helps us to avoid cross bank + /// copies. InstType deppends on context. + enum InstType { + /// Temporary type, when visit(..., nullptr) finishes will convert to one of + /// the remaining types: Integer, FloatingPoint or Ambiguous. + NotDetermined, + /// Connected with instruction that interprets 'bags of bits' as integers. + /// Select gprb to avoid cross bank copies. + Integer, + /// Connected with instruction that interprets 'bags of bits' as floating + /// point numbers. Select fprb to avoid cross bank copies. + FloatingPoint, + /// Represents moving 'bags of bits' around. Select same bank for entire + /// chain to avoid cross bank copies. Currently we select fprb for s64 and + /// gprb for s32 Ambiguous operands. + Ambiguous + }; + + /// Some generic instructions have operands that can be mapped to either fprb + /// or gprb e.g. for G_LOAD we consider only operand 0 as ambiguous, operand 1 + /// is always gprb since it is a pointer. + /// This class provides containers for MI's ambiguous: + /// DefUses : MachineInstrs that use one of MI's ambiguous def operands. + /// UseDefs : MachineInstrs that define MI's ambiguous use operands. + class AmbiguousRegDefUseContainer { + SmallVector<MachineInstr *, 2> DefUses; + SmallVector<MachineInstr *, 2> UseDefs; + + void addDefUses(Register Reg, const MachineRegisterInfo &MRI); + void addUseDef(Register Reg, const MachineRegisterInfo &MRI); + + /// Skip copy instructions until we get to a non-copy instruction or to a + /// copy with phys register as def. Used during search for DefUses. + /// MI : %5 = COPY %4 + /// %6 = COPY %5 + /// $v0 = COPY %6 <- we want this one. + MachineInstr *skipCopiesOutgoing(MachineInstr *MI) const; + + /// Skip copy instructions until we get to a non-copy instruction or to a + /// copy with phys register as use. Used during search for UseDefs. + /// %1 = COPY $a1 <- we want this one. + /// %2 = COPY %1 + /// MI = %3 = COPY %2 + MachineInstr *skipCopiesIncoming(MachineInstr *MI) const; + + public: + AmbiguousRegDefUseContainer(const MachineInstr *MI); + SmallVectorImpl<MachineInstr *> &getDefUses() { return DefUses; } + SmallVectorImpl<MachineInstr *> &getUseDefs() { return UseDefs; } + }; + + class TypeInfoForMF { + /// MachineFunction name is used to recognise when MF changes. + std::string MFName = ""; + /// <key, value> : value is vector of all MachineInstrs that are waiting for + /// key to figure out type of some of its ambiguous operands. + DenseMap<const MachineInstr *, SmallVector<const MachineInstr *, 2>> + WaitingQueues; + /// Recorded InstTypes for visited instructions. + DenseMap<const MachineInstr *, InstType> Types; + + /// Recursively visit MI's adjacent instructions and find MI's InstType. + bool visit(const MachineInstr *MI, const MachineInstr *WaitingForTypeOfMI); + + /// Visit MI's adjacent UseDefs or DefUses. + bool visitAdjacentInstrs(const MachineInstr *MI, + SmallVectorImpl<MachineInstr *> &AdjacentInstrs, + bool isDefUse); + + /// Set type for MI, and recursively for all instructions that are + /// waiting for MI's type. + void setTypes(const MachineInstr *MI, InstType ITy); + + /// InstType for MI is determined, set it to InstType that corresponds to + /// physical regisiter that is operand number Op in CopyInst. + void setTypesAccordingToPhysicalRegister(const MachineInstr *MI, + const MachineInstr *CopyInst, + unsigned Op); + + /// Set default values for MI in order to start visit. + void startVisit(const MachineInstr *MI) { + Types.try_emplace(MI, InstType::NotDetermined); + WaitingQueues.try_emplace(MI); + } + + /// Returns true if instruction was already visited. Type might not be + /// determined at this point but will be when visit(..., nullptr) finishes. + bool wasVisited(const MachineInstr *MI) const { return Types.count(MI); }; + + /// Returns recorded type for instruction. + const InstType &getRecordedTypeForInstr(const MachineInstr *MI) const { + assert(wasVisited(MI) && "Instruction was not visited!"); + return Types.find(MI)->getSecond(); + }; + + /// Change recorded type for instruction. + void changeRecordedTypeForInstr(const MachineInstr *MI, InstType InstTy) { + assert(wasVisited(MI) && "Instruction was not visited!"); + Types.find(MI)->getSecond() = InstTy; + }; + + /// Returns WaitingQueue for instruction. + const SmallVectorImpl<const MachineInstr *> & + getWaitingQueueFor(const MachineInstr *MI) const { + assert(WaitingQueues.count(MI) && "Instruction was not visited!"); + return WaitingQueues.find(MI)->getSecond(); + }; + + /// Add WaitingForMI to MI's WaitingQueue. + void addToWaitingQueue(const MachineInstr *MI, + const MachineInstr *WaitingForMI) { + assert(WaitingQueues.count(MI) && "Instruction was not visited!"); + WaitingQueues.find(MI)->getSecond().push_back(WaitingForMI); + }; + + public: + InstType determineInstType(const MachineInstr *MI); + + void cleanupIfNewFunction(llvm::StringRef FunctionName); + }; }; } // end namespace llvm #endif diff --git a/lib/Target/Mips/MipsRegisterBanks.td b/lib/Target/Mips/MipsRegisterBanks.td index 5f1687048fac..14a0181f8f11 100644 --- a/lib/Target/Mips/MipsRegisterBanks.td +++ b/lib/Target/Mips/MipsRegisterBanks.td @@ -1,9 +1,8 @@ //===- MipsRegisterBank.td ---------------------------------*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -11,3 +10,5 @@ //===----------------------------------------------------------------------===// def GPRBRegBank : RegisterBank<"GPRB", [GPR32]>; + +def FPRBRegBank : RegisterBank<"FPRB", [FGR64, AFGR64]>; diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp index 3c108c2ba9b7..7b02d126eb28 100644 --- a/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/lib/Target/Mips/MipsRegisterInfo.cpp @@ -1,9 +1,8 @@ //===- MipsRegisterInfo.cpp - MIPS Register Information -------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -160,8 +159,6 @@ getReservedRegs(const MachineFunction &MF) const { BitVector Reserved(getNumRegs()); const MipsSubtarget &Subtarget = MF.getSubtarget<MipsSubtarget>(); - using RegIter = TargetRegisterClass::const_iterator; - for (unsigned I = 0; I < array_lengthof(ReservedGPR32); ++I) Reserved.set(ReservedGPR32[I]); @@ -183,14 +180,12 @@ getReservedRegs(const MachineFunction &MF) const { if (Subtarget.isFP64bit()) { // Reserve all registers in AFGR64. - for (RegIter Reg = Mips::AFGR64RegClass.begin(), - EReg = Mips::AFGR64RegClass.end(); Reg != EReg; ++Reg) - Reserved.set(*Reg); + for (MCPhysReg Reg : Mips::AFGR64RegClass) + Reserved.set(Reg); } else { // Reserve all registers in FGR64. - for (RegIter Reg = Mips::FGR64RegClass.begin(), - EReg = Mips::FGR64RegClass.end(); Reg != EReg; ++Reg) - Reserved.set(*Reg); + for (MCPhysReg Reg : Mips::FGR64RegClass) + Reserved.set(Reg); } // Reserve FP if this function should have a dedicated frame pointer register. if (Subtarget.getFrameLowering()->hasFP(MF)) { @@ -222,14 +217,8 @@ getReservedRegs(const MachineFunction &MF) const { Reserved.set(Mips::DSPOutFlag); // Reserve MSA control registers. - Reserved.set(Mips::MSAIR); - Reserved.set(Mips::MSACSR); - Reserved.set(Mips::MSAAccess); - Reserved.set(Mips::MSASave); - Reserved.set(Mips::MSAModify); - Reserved.set(Mips::MSARequest); - Reserved.set(Mips::MSAMap); - Reserved.set(Mips::MSAUnmap); + for (MCPhysReg Reg : Mips::MSACtrlRegClass) + Reserved.set(Reg); // Reserve RA if in mips16 mode. if (Subtarget.inMips16Mode()) { @@ -248,11 +237,6 @@ getReservedRegs(const MachineFunction &MF) const { Reserved.set(Mips::GP_64); } - if (Subtarget.isABI_O32() && !Subtarget.useOddSPReg()) { - for (const auto &Reg : Mips::OddSPRegClass) - Reserved.set(Reg); - } - return Reserved; } @@ -293,7 +277,7 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, eliminateFI(MI, FIOperandNum, FrameIndex, stackSize, spOffset); } -unsigned MipsRegisterInfo:: +Register MipsRegisterInfo:: getFrameRegister(const MachineFunction &MF) const { const MipsSubtarget &Subtarget = MF.getSubtarget<MipsSubtarget>(); const TargetFrameLowering *TFI = Subtarget.getFrameLowering(); @@ -322,8 +306,8 @@ bool MipsRegisterInfo::canRealignStack(const MachineFunction &MF) const { unsigned FP = Subtarget.isGP32bit() ? Mips::FP : Mips::FP_64; unsigned BP = Subtarget.isGP32bit() ? Mips::S7 : Mips::S7_64; - // Support dynamic stack realignment only for targets with standard encoding. - if (!Subtarget.hasStandardEncoding()) + // Support dynamic stack realignment for all targets except Mips16. + if (Subtarget.inMips16Mode()) return false; // We can't perform dynamic stack realignment if we can't reserve the diff --git a/lib/Target/Mips/MipsRegisterInfo.h b/lib/Target/Mips/MipsRegisterInfo.h index b84aaad05eb5..4ed32b09718b 100644 --- a/lib/Target/Mips/MipsRegisterInfo.h +++ b/lib/Target/Mips/MipsRegisterInfo.h @@ -1,9 +1,8 @@ //===- MipsRegisterInfo.h - Mips Register Information Impl ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -70,7 +69,7 @@ public: bool canRealignStack(const MachineFunction &MF) const override; /// Debug information queries. - unsigned getFrameRegister(const MachineFunction &MF) const override; + Register getFrameRegister(const MachineFunction &MF) const override; /// Return GPR register class. virtual const TargetRegisterClass *intRegClass(unsigned Size) const = 0; diff --git a/lib/Target/Mips/MipsRegisterInfo.td b/lib/Target/Mips/MipsRegisterInfo.td index a943a0ad4094..8a6279da46b7 100644 --- a/lib/Target/Mips/MipsRegisterInfo.td +++ b/lib/Target/Mips/MipsRegisterInfo.td @@ -1,9 +1,8 @@ //===-- MipsRegisterInfo.td - Mips Register defs -----------*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -259,6 +258,11 @@ let Namespace = "Mips" in { def MSARequest : MipsReg<5, "5">; def MSAMap : MipsReg<6, "6">; def MSAUnmap : MipsReg<7, "7">; + // MSA-ASE fake control registers. + // These registers do not exist, but instructions like `cfcmsa` + // and `ctcmsa` allows to specify them. + foreach I = 8-31 in + def MSA#I : MipsReg<#I, ""#I>; // Octeon multiplier and product registers def MPL0 : MipsReg<0, "mpl0">; @@ -383,10 +387,14 @@ def CPUSPReg : RegisterClass<"Mips", [i32], 32, (add SP)>, Unallocatable; // 32bit fp: // * FGR32 - 16 32-bit even registers // * FGR32 - 32 32-bit registers (single float only mode) -def FGR32 : RegisterClass<"Mips", [f32], 32, (sequence "F%u", 0, 31)>; - -def FGRH32 : RegisterClass<"Mips", [f32], 32, (sequence "F_HI%u", 0, 31)>, - Unallocatable; +def FGR32 : RegisterClass<"Mips", [f32], 32, (sequence "F%u", 0, 31)> { + // Do not allocate odd registers when given -mattr=+nooddspreg. + let AltOrders = [(decimate FGR32, 2)]; + let AltOrderSelect = [{ + const auto & S = MF.getSubtarget<MipsSubtarget>(); + return S.isABI_O32() && !S.useOddSPReg(); + }]; +} def AFGR64 : RegisterClass<"Mips", [f64], 64, (add // Return Values and Arguments @@ -400,16 +408,14 @@ def AFGR64 : RegisterClass<"Mips", [f64], 64, (add // Callee save D10, D11, D12, D13, D14, D15)>; -def FGR64 : RegisterClass<"Mips", [f64], 64, (sequence "D%u_64", 0, 31)>; - -// Used to reserve odd registers when given -mattr=+nooddspreg -// FIXME: Remove double precision registers from this set. -def OddSP : RegisterClass<"Mips", [f32], 32, - (add (decimate (sequence "F%u", 1, 31), 2), - (decimate (sequence "F_HI%u", 1, 31), 2), - (decimate (sequence "D%u", 1, 15), 2), - (decimate (sequence "D%u_64", 1, 31), 2))>, - Unallocatable; +def FGR64 : RegisterClass<"Mips", [f64], 64, (sequence "D%u_64", 0, 31)> { + // Do not allocate odd registers when given -mattr=+nooddspreg. + let AltOrders = [(decimate FGR64, 2)]; + let AltOrderSelect = [{ + const auto & S = MF.getSubtarget<MipsSubtarget>(); + return S.isABI_O32() && !S.useOddSPReg(); + }]; +} // FP control registers. def CCR : RegisterClass<"Mips", [i32], 32, (sequence "FCR%u", 0, 31)>, @@ -437,7 +443,8 @@ def MSA128WEvens: RegisterClass<"Mips", [v4i32, v4f32], 128, (decimate (sequence "W%u", 0, 31), 2)>; def MSACtrl: RegisterClass<"Mips", [i32], 32, (add - MSAIR, MSACSR, MSAAccess, MSASave, MSAModify, MSARequest, MSAMap, MSAUnmap)>; + MSAIR, MSACSR, MSAAccess, MSASave, MSAModify, MSARequest, MSAMap, MSAUnmap, + (sequence "MSA%u", 8, 31))>, Unallocatable; // Hi/Lo Registers def LO32 : RegisterClass<"Mips", [i32], 32, (add LO0)>; @@ -591,11 +598,6 @@ def StrictlyFGR32AsmOperand : MipsAsmRegOperand { let PredicateMethod = "isStrictlyFGRAsmReg"; } -def FGRH32AsmOperand : MipsAsmRegOperand { - let Name = "FGRH32AsmReg"; - let PredicateMethod = "isFGRAsmReg"; -} - def FCCRegsAsmOperand : MipsAsmRegOperand { let Name = "FCCAsmReg"; } @@ -703,10 +705,6 @@ def FGRCCOpnd : RegisterOperand<FGRCC> { let ParserMatchClass = FGR32AsmOperand; } -def FGRH32Opnd : RegisterOperand<FGRH32> { - let ParserMatchClass = FGRH32AsmOperand; -} - def FCCRegsOpnd : RegisterOperand<FCC> { let ParserMatchClass = FCCRegsAsmOperand; } diff --git a/lib/Target/Mips/MipsSEFrameLowering.cpp b/lib/Target/Mips/MipsSEFrameLowering.cpp index ef1b3c09bdc4..4c6cc1ef771c 100644 --- a/lib/Target/Mips/MipsSEFrameLowering.cpp +++ b/lib/Target/Mips/MipsSEFrameLowering.cpp @@ -1,9 +1,8 @@ //===- MipsSEFrameLowering.cpp - Mips32/64 Frame Information --------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/MipsSEFrameLowering.h b/lib/Target/Mips/MipsSEFrameLowering.h index cb2119d6880b..78ffe161d9c6 100644 --- a/lib/Target/Mips/MipsSEFrameLowering.h +++ b/lib/Target/Mips/MipsSEFrameLowering.h @@ -1,9 +1,8 @@ //===- MipsSEFrameLowering.h - Mips32/64 frame lowering ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MipsSEISelDAGToDAG.cpp b/lib/Target/Mips/MipsSEISelDAGToDAG.cpp index cf196b597278..703f99f37dd1 100644 --- a/lib/Target/Mips/MipsSEISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsSEISelDAGToDAG.cpp @@ -1,9 +1,8 @@ //===-- MipsSEISelDAGToDAG.cpp - A Dag to Dag Inst Selector for MipsSE ----===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -76,18 +75,8 @@ void MipsSEDAGToDAGISel::addDSPCtrlRegOperands(bool IsDef, MachineInstr &MI, } unsigned MipsSEDAGToDAGISel::getMSACtrlReg(const SDValue RegIdx) const { - switch (cast<ConstantSDNode>(RegIdx)->getZExtValue()) { - default: - llvm_unreachable("Could not map int to register"); - case 0: return Mips::MSAIR; - case 1: return Mips::MSACSR; - case 2: return Mips::MSAAccess; - case 3: return Mips::MSASave; - case 4: return Mips::MSAModify; - case 5: return Mips::MSARequest; - case 6: return Mips::MSAMap; - case 7: return Mips::MSAUnmap; - } + uint64_t RegNum = cast<ConstantSDNode>(RegIdx)->getZExtValue(); + return Mips::MSACtrlRegClass.getRegister(RegNum); } bool MipsSEDAGToDAGISel::replaceUsesWithZeroReg(MachineRegisterInfo *MRI, @@ -135,97 +124,8 @@ bool MipsSEDAGToDAGISel::replaceUsesWithZeroReg(MachineRegisterInfo *MRI, return true; } -void MipsSEDAGToDAGISel::initGlobalBaseReg(MachineFunction &MF) { - MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); - - if (!MipsFI->globalBaseRegSet()) - return; - - MachineBasicBlock &MBB = MF.front(); - MachineBasicBlock::iterator I = MBB.begin(); - MachineRegisterInfo &RegInfo = MF.getRegInfo(); - const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); - DebugLoc DL; - unsigned V0, V1, GlobalBaseReg = MipsFI->getGlobalBaseReg(); - const TargetRegisterClass *RC; - const MipsABIInfo &ABI = static_cast<const MipsTargetMachine &>(TM).getABI(); - RC = (ABI.IsN64()) ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; - - V0 = RegInfo.createVirtualRegister(RC); - V1 = RegInfo.createVirtualRegister(RC); - - if (ABI.IsN64()) { - MF.getRegInfo().addLiveIn(Mips::T9_64); - MBB.addLiveIn(Mips::T9_64); - - // lui $v0, %hi(%neg(%gp_rel(fname))) - // daddu $v1, $v0, $t9 - // daddiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname))) - const GlobalValue *FName = &MF.getFunction(); - BuildMI(MBB, I, DL, TII.get(Mips::LUi64), V0) - .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI); - BuildMI(MBB, I, DL, TII.get(Mips::DADDu), V1).addReg(V0) - .addReg(Mips::T9_64); - BuildMI(MBB, I, DL, TII.get(Mips::DADDiu), GlobalBaseReg).addReg(V1) - .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO); - return; - } - - if (!MF.getTarget().isPositionIndependent()) { - // Set global register to __gnu_local_gp. - // - // lui $v0, %hi(__gnu_local_gp) - // addiu $globalbasereg, $v0, %lo(__gnu_local_gp) - BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0) - .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_HI); - BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V0) - .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_LO); - return; - } - - MF.getRegInfo().addLiveIn(Mips::T9); - MBB.addLiveIn(Mips::T9); - - if (ABI.IsN32()) { - // lui $v0, %hi(%neg(%gp_rel(fname))) - // addu $v1, $v0, $t9 - // addiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname))) - const GlobalValue *FName = &MF.getFunction(); - BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0) - .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI); - BuildMI(MBB, I, DL, TII.get(Mips::ADDu), V1).addReg(V0).addReg(Mips::T9); - BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V1) - .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO); - return; - } - - assert(ABI.IsO32()); - - // For O32 ABI, the following instruction sequence is emitted to initialize - // the global base register: - // - // 0. lui $2, %hi(_gp_disp) - // 1. addiu $2, $2, %lo(_gp_disp) - // 2. addu $globalbasereg, $2, $t9 - // - // We emit only the last instruction here. - // - // GNU linker requires that the first two instructions appear at the beginning - // of a function and no instructions be inserted before or between them. - // The two instructions are emitted during lowering to MC layer in order to - // avoid any reordering. - // - // Register $2 (Mips::V0) is added to the list of live-in registers to ensure - // the value instruction 1 (addiu) defines is valid when instruction 2 (addu) - // reads it. - MF.getRegInfo().addLiveIn(Mips::V0); - MBB.addLiveIn(Mips::V0); - BuildMI(MBB, I, DL, TII.get(Mips::ADDu), GlobalBaseReg) - .addReg(Mips::V0).addReg(Mips::T9); -} - void MipsSEDAGToDAGISel::processFunctionAfterISel(MachineFunction &MF) { - initGlobalBaseReg(MF); + MF.getInfo<MipsFunctionInfo>()->initGlobalBaseReg(); MachineRegisterInfo *MRI = &MF.getRegInfo(); @@ -1337,6 +1237,7 @@ SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32)); return false; case InlineAsm::Constraint_m: + case InlineAsm::Constraint_o: if (selectAddrRegImm16(Op, Base, Offset)) { OutOps.push_back(Base); OutOps.push_back(Offset); diff --git a/lib/Target/Mips/MipsSEISelDAGToDAG.h b/lib/Target/Mips/MipsSEISelDAGToDAG.h index eb3657aae050..ce594e1fb4fa 100644 --- a/lib/Target/Mips/MipsSEISelDAGToDAG.h +++ b/lib/Target/Mips/MipsSEISelDAGToDAG.h @@ -1,9 +1,8 @@ //===-- MipsSEISelDAGToDAG.h - A Dag to Dag Inst Selector for MipsSE -----===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -131,10 +130,6 @@ private: void processFunctionAfterISel(MachineFunction &MF) override; - // Insert instructions to initialize the global base register in the - // first MBB of the function. - void initGlobalBaseReg(MachineFunction &MF); - bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, std::vector<SDValue> &OutOps) override; diff --git a/lib/Target/Mips/MipsSEISelLowering.cpp b/lib/Target/Mips/MipsSEISelLowering.cpp index a78e544c35f0..edf57a3840d1 100644 --- a/lib/Target/Mips/MipsSEISelLowering.cpp +++ b/lib/Target/Mips/MipsSEISelLowering.cpp @@ -1,9 +1,8 @@ //===- MipsSEISelLowering.cpp - MipsSE DAG Lowering Interface -------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -214,6 +213,11 @@ MipsSETargetLowering::MipsSETargetLowering(const MipsTargetMachine &TM, setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::Other, Custom); setOperationAction(ISD::INTRINSIC_VOID, MVT::Other, Custom); + if (Subtarget.hasMips32r2() && !Subtarget.useSoftFloat() && + !Subtarget.hasMips64()) { + setOperationAction(ISD::BITCAST, MVT::i64, Custom); + } + if (NoDPLoadStore) { setOperationAction(ISD::LOAD, MVT::f64, Custom); setOperationAction(ISD::STORE, MVT::f64, Custom); @@ -415,11 +419,8 @@ SDValue MipsSETargetLowering::lowerSELECT(SDValue Op, SelectionDAG &DAG) const { Op->getOperand(2)); } -bool -MipsSETargetLowering::allowsMisalignedMemoryAccesses(EVT VT, - unsigned, - unsigned, - bool *Fast) const { +bool MipsSETargetLowering::allowsMisalignedMemoryAccesses( + EVT VT, unsigned, unsigned, MachineMemOperand::Flags, bool *Fast) const { MVT::SimpleValueType SVT = VT.getSimpleVT().SimpleTy; if (Subtarget.systemSupportsUnalignedAccess()) { @@ -463,6 +464,7 @@ SDValue MipsSETargetLowering::LowerOperation(SDValue Op, case ISD::BUILD_VECTOR: return lowerBUILD_VECTOR(Op, DAG); case ISD::VECTOR_SHUFFLE: return lowerVECTOR_SHUFFLE(Op, DAG); case ISD::SELECT: return lowerSELECT(Op, DAG); + case ISD::BITCAST: return lowerBITCAST(Op, DAG); } return MipsTargetLowering::LowerOperation(Op, DAG); @@ -714,8 +716,31 @@ static bool shouldTransformMulToShiftsAddsSubs(APInt C, EVT VT, SelectionDAG &DAG, const MipsSubtarget &Subtarget) { // Estimate the number of operations the below transform will turn a - // constant multiply into. The number is approximately how many powers - // of two summed together that the constant can be broken down into. + // constant multiply into. The number is approximately equal to the minimal + // number of powers of two that constant can be broken down to by adding + // or subtracting them. + // + // If we have taken more than 12[1] / 8[2] steps to attempt the + // optimization for a native sized value, it is more than likely that this + // optimization will make things worse. + // + // [1] MIPS64 requires 6 instructions at most to materialize any constant, + // multiplication requires at least 4 cycles, but another cycle (or two) + // to retrieve the result from the HI/LO registers. + // + // [2] For MIPS32, more than 8 steps is expensive as the constant could be + // materialized in 2 instructions, multiplication requires at least 4 + // cycles, but another cycle (or two) to retrieve the result from the + // HI/LO registers. + // + // TODO: + // - MaxSteps needs to consider the `VT` of the constant for the current + // target. + // - Consider to perform this optimization after type legalization. + // That allows to remove a workaround for types not supported natively. + // - Take in account `-Os, -Oz` flags because this optimization + // increases code size. + unsigned MaxSteps = Subtarget.isABI_O32() ? 8 : 12; SmallVector<APInt, 16> WorkStack(1, C); unsigned Steps = 0; @@ -727,6 +752,9 @@ static bool shouldTransformMulToShiftsAddsSubs(APInt C, EVT VT, if (Val == 0 || Val == 1) continue; + if (Steps >= MaxSteps) + return false; + if (Val.isPowerOf2()) { ++Steps; continue; @@ -735,36 +763,15 @@ static bool shouldTransformMulToShiftsAddsSubs(APInt C, EVT VT, APInt Floor = APInt(BitWidth, 1) << Val.logBase2(); APInt Ceil = Val.isNegative() ? APInt(BitWidth, 0) : APInt(BitWidth, 1) << C.ceilLogBase2(); - if ((Val - Floor).ule(Ceil - Val)) { WorkStack.push_back(Floor); WorkStack.push_back(Val - Floor); - ++Steps; - continue; + } else { + WorkStack.push_back(Ceil); + WorkStack.push_back(Ceil - Val); } - WorkStack.push_back(Ceil); - WorkStack.push_back(Ceil - Val); ++Steps; - - // If we have taken more than 12[1] / 8[2] steps to attempt the - // optimization for a native sized value, it is more than likely that this - // optimization will make things worse. - // - // [1] MIPS64 requires 6 instructions at most to materialize any constant, - // multiplication requires at least 4 cycles, but another cycle (or two) - // to retrieve the result from the HI/LO registers. - // - // [2] For MIPS32, more than 8 steps is expensive as the constant could be - // materialized in 2 instructions, multiplication requires at least 4 - // cycles, but another cycle (or two) to retrieve the result from the - // HI/LO registers. - - if (Steps > 12 && (Subtarget.isABI_N32() || Subtarget.isABI_N64())) - return false; - - if (Steps > 8 && Subtarget.isABI_O32()) - return false; } // If the value being multiplied is not supported natively, we have to pay @@ -1221,6 +1228,36 @@ SDValue MipsSETargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const { Nd.getMemOperand()->getFlags(), Nd.getAAInfo()); } +SDValue MipsSETargetLowering::lowerBITCAST(SDValue Op, + SelectionDAG &DAG) const { + SDLoc DL(Op); + MVT Src = Op.getOperand(0).getValueType().getSimpleVT(); + MVT Dest = Op.getValueType().getSimpleVT(); + + // Bitcast i64 to double. + if (Src == MVT::i64 && Dest == MVT::f64) { + SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, + Op.getOperand(0), DAG.getIntPtrConstant(0, DL)); + SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, + Op.getOperand(0), DAG.getIntPtrConstant(1, DL)); + return DAG.getNode(MipsISD::BuildPairF64, DL, MVT::f64, Lo, Hi); + } + + // Bitcast double to i64. + if (Src == MVT::f64 && Dest == MVT::i64) { + SDValue Lo = + DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, Op.getOperand(0), + DAG.getConstant(0, DL, MVT::i32)); + SDValue Hi = + DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, Op.getOperand(0), + DAG.getConstant(1, DL, MVT::i32)); + return DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, Lo, Hi); + } + + // Skip other cases of bitcast and use default lowering. + return SDValue(); +} + SDValue MipsSETargetLowering::lowerMulDiv(SDValue Op, unsigned NewOpc, bool HasLo, bool HasHi, SelectionDAG &DAG) const { @@ -1379,9 +1416,10 @@ static SDValue lowerMSASplatZExt(SDValue Op, unsigned OpNr, SelectionDAG &DAG) { static SDValue lowerMSASplatImm(SDValue Op, unsigned ImmOp, SelectionDAG &DAG, bool IsSigned = false) { + auto *CImm = cast<ConstantSDNode>(Op->getOperand(ImmOp)); return DAG.getConstant( APInt(Op->getValueType(0).getScalarType().getSizeInBits(), - Op->getConstantOperandVal(ImmOp), IsSigned), + IsSigned ? CImm->getSExtValue() : CImm->getZExtValue(), IsSigned), SDLoc(Op), Op->getValueType(0)); } @@ -3725,8 +3763,8 @@ MipsSETargetLowering::emitFPEXTEND_PSEUDO(MachineInstr &MI, const TargetInstrInfo *TII = Subtarget.getInstrInfo(); DebugLoc DL = MI.getDebugLoc(); - unsigned Fd = MI.getOperand(0).getReg(); - unsigned Ws = MI.getOperand(1).getReg(); + Register Fd = MI.getOperand(0).getReg(); + Register Ws = MI.getOperand(1).getReg(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); const TargetRegisterClass *GPRRC = @@ -3734,10 +3772,10 @@ MipsSETargetLowering::emitFPEXTEND_PSEUDO(MachineInstr &MI, unsigned MTC1Opc = IsFGR64onMips64 ? Mips::DMTC1 : (IsFGR64onMips32 ? Mips::MTC1_D64 : Mips::MTC1); - unsigned COPYOpc = IsFGR64onMips64 ? Mips::COPY_S_D : Mips::COPY_S_W; + Register COPYOpc = IsFGR64onMips64 ? Mips::COPY_S_D : Mips::COPY_S_W; - unsigned Wtemp = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass); - unsigned WPHI = Wtemp; + Register Wtemp = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass); + Register WPHI = Wtemp; BuildMI(*BB, MI, DL, TII->get(Mips::FEXUPR_W), Wtemp).addReg(Ws); if (IsFGR64) { @@ -3746,15 +3784,15 @@ MipsSETargetLowering::emitFPEXTEND_PSEUDO(MachineInstr &MI, } // Perform the safety regclass copy mentioned above. - unsigned Rtemp = RegInfo.createVirtualRegister(GPRRC); - unsigned FPRPHI = IsFGR64onMips32 + Register Rtemp = RegInfo.createVirtualRegister(GPRRC); + Register FPRPHI = IsFGR64onMips32 ? RegInfo.createVirtualRegister(&Mips::FGR64RegClass) : Fd; BuildMI(*BB, MI, DL, TII->get(COPYOpc), Rtemp).addReg(WPHI).addImm(0); BuildMI(*BB, MI, DL, TII->get(MTC1Opc), FPRPHI).addReg(Rtemp); if (IsFGR64onMips32) { - unsigned Rtemp2 = RegInfo.createVirtualRegister(GPRRC); + Register Rtemp2 = RegInfo.createVirtualRegister(GPRRC); BuildMI(*BB, MI, DL, TII->get(Mips::COPY_S_W), Rtemp2) .addReg(WPHI) .addImm(1); diff --git a/lib/Target/Mips/MipsSEISelLowering.h b/lib/Target/Mips/MipsSEISelLowering.h index 761ff3b1fa4d..433d019332cf 100644 --- a/lib/Target/Mips/MipsSEISelLowering.h +++ b/lib/Target/Mips/MipsSEISelLowering.h @@ -1,9 +1,8 @@ //===- MipsSEISelLowering.h - MipsSE DAG Lowering Interface -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -41,9 +40,10 @@ class TargetRegisterClass; void addMSAFloatType(MVT::SimpleValueType Ty, const TargetRegisterClass *RC); - bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AS = 0, - unsigned Align = 1, - bool *Fast = nullptr) const override; + bool allowsMisalignedMemoryAccesses( + EVT VT, unsigned AS = 0, unsigned Align = 1, + MachineMemOperand::Flags Flags = MachineMemOperand::MONone, + bool *Fast = nullptr) const override; SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; @@ -73,6 +73,7 @@ class TargetRegisterClass; SDValue lowerLOAD(SDValue Op, SelectionDAG &DAG) const; SDValue lowerSTORE(SDValue Op, SelectionDAG &DAG) const; + SDValue lowerBITCAST(SDValue Op, SelectionDAG &DAG) const; SDValue lowerMulDiv(SDValue Op, unsigned NewOpc, bool HasLo, bool HasHi, SelectionDAG &DAG) const; diff --git a/lib/Target/Mips/MipsSEInstrInfo.cpp b/lib/Target/Mips/MipsSEInstrInfo.cpp index c7ab90ed2a3b..4e49f5e7d9d1 100644 --- a/lib/Target/Mips/MipsSEInstrInfo.cpp +++ b/lib/Target/Mips/MipsSEInstrInfo.cpp @@ -1,9 +1,8 @@ //===-- MipsSEInstrInfo.cpp - Mips32/64 Instruction Information -----------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -12,7 +11,7 @@ //===----------------------------------------------------------------------===// #include "MipsSEInstrInfo.h" -#include "InstPrinter/MipsInstPrinter.h" +#include "MCTargetDesc/MipsInstPrinter.h" #include "MipsAnalyzeImmediate.h" #include "MipsMachineFunction.h" #include "MipsTargetMachine.h" @@ -447,6 +446,9 @@ bool MipsSEInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { case Mips::PseudoMTLOHI_DSP: expandPseudoMTLoHi(MBB, MI, Mips::MTLO_DSP, Mips::MTHI_DSP, true); break; + case Mips::PseudoMTLOHI_MM: + expandPseudoMTLoHi(MBB, MI, Mips::MTLO_MM, Mips::MTHI_MM, false); + break; case Mips::PseudoCVT_S_W: expandCvtFPInt(MBB, MI, Mips::CVT_S_W, Mips::MTC1, false); break; diff --git a/lib/Target/Mips/MipsSEInstrInfo.h b/lib/Target/Mips/MipsSEInstrInfo.h index fce0fe5f58ad..3111d1c21a0a 100644 --- a/lib/Target/Mips/MipsSEInstrInfo.h +++ b/lib/Target/Mips/MipsSEInstrInfo.h @@ -1,9 +1,8 @@ //===-- MipsSEInstrInfo.h - Mips32/64 Instruction Information ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/MipsSERegisterInfo.cpp b/lib/Target/Mips/MipsSERegisterInfo.cpp index e7d720a4b769..f4b164d5c0ab 100644 --- a/lib/Target/Mips/MipsSERegisterInfo.cpp +++ b/lib/Target/Mips/MipsSERegisterInfo.cpp @@ -1,9 +1,8 @@ //===-- MipsSERegisterInfo.cpp - MIPS32/64 Register Information -== -------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/MipsSERegisterInfo.h b/lib/Target/Mips/MipsSERegisterInfo.h index ebae1909d233..82ddf40f56a7 100644 --- a/lib/Target/Mips/MipsSERegisterInfo.h +++ b/lib/Target/Mips/MipsSERegisterInfo.h @@ -1,9 +1,8 @@ //===-- MipsSERegisterInfo.h - Mips32/64 Register Information ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Target/Mips/MipsSchedule.td b/lib/Target/Mips/MipsSchedule.td index 410fa655a225..0c0ddeab22c4 100644 --- a/lib/Target/Mips/MipsSchedule.td +++ b/lib/Target/Mips/MipsSchedule.td @@ -1,9 +1,8 @@ //===-- MipsSchedule.td - Mips Scheduling Definitions ------*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MipsScheduleGeneric.td b/lib/Target/Mips/MipsScheduleGeneric.td index 80ffe7ada7c8..e8a0a30b8e9b 100644 --- a/lib/Target/Mips/MipsScheduleGeneric.td +++ b/lib/Target/Mips/MipsScheduleGeneric.td @@ -1,9 +1,8 @@ //=- MipsScheduleGeneric.td - Generic Scheduling Definitions -*- tablegen -*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -25,11 +24,11 @@ def MipsGenericModel : SchedMachineModel { int HighLatency = 37; list<Predicate> UnsupportedFeatures = []; - let CompleteModel = 0; + let CompleteModel = 1; let PostRAScheduler = 1; // FIXME: Remove when all errors have been fixed. - let FullInstRWOverlapCheck = 0; + let FullInstRWOverlapCheck = 1; } let SchedModel = MipsGenericModel in { @@ -42,35 +41,122 @@ def GenericIssueALU : ProcResource<1> { let Super = GenericALU; } def GenericWriteALU : SchedWriteRes<[GenericIssueALU]>; -// and, lui, nor, or, slti, sltiu, sub, subu, xor -// add, addi, addiu, addu, andi, ori, rotr, se[bh], sllv?, sr[al]v?, slt, sltu, -// xori -def : ItinRW<[GenericWriteALU], [II_ADD, II_ADDU, II_ADDI, II_ADDIU, II_ANDI, - II_AND, II_ANDI, II_CLO, II_CLZ, II_EXT, - II_INS, II_LUI, II_MULT, II_MULTU, II_NOR, - II_ORI, II_OR, II_ROTR, II_ROTRV, II_SEB, - II_SEH, II_SLTI_SLTIU, II_SLT_SLTU, II_SLL, - II_SRA, II_SRL, II_SLLV, II_SRAV, II_SRLV, - II_SSNOP, II_SUB, II_SUBU, II_WSBH, II_XOR, - II_XORI]>; +// add, addi, addiu, addu, and, andi, clo, clz, ext, ins, lui, nor, or, ori, +// rotr, rotrv, seb, seh, sll, sllv, slt, slti, sltiu, sltu, sra, srav, srl, +// srlv, ssnop, sub, subu, wsbh, xor, xori +def : InstRW<[GenericWriteALU], (instrs ADD, ADDi, ADDiu, ADDu, AND, ANDi, + CLO, CLZ, EXT, INS, LEA_ADDiu, LUi, NOP, + NOR, OR, ORi, ROTR, ROTRV, SEB, SEH, SLL, + SLLV, SLT, SLTi, SLTiu, SLTu, SRA, SRAV, SRL, + SRLV, SSNOP, SUB, SUBu, WSBH, XOR, XORi)>; def : InstRW<[GenericWriteALU], (instrs COPY)>; +// MIPSR6 +// ====== + +// addiupc, align, aluipc, aui, auipc, bitswap, clo, clz, lsa, seleqz, selnez +def : InstRW<[GenericWriteALU], (instrs ADDIUPC, ALIGN, ALUIPC, AUI, + AUIPC, BITSWAP, CLO_R6, CLZ_R6, LSA_R6, + SELEQZ, SELNEZ)>; + +// MIPS16e +// ======= + +def : InstRW<[GenericWriteALU], (instrs AddiuRxImmX16, AddiuRxRxImm16, + AddiuRxRxImmX16, AddiuRxRyOffMemX16, + AddiuRxPcImmX16, AddiuSpImm16, AddiuSpImmX16, + AdduRxRyRz16, AndRxRxRy16, CmpRxRy16, + CmpiRxImm16, CmpiRxImmX16, LiRxImm16, + LiRxImmX16, LiRxImmAlignX16, Move32R16, + MoveR3216, Mfhi16, Mflo16, NegRxRy16, + NotRxRy16, OrRxRxRy16, SebRx16, SehRx16, + SllX16, SllvRxRy16, SltiRxImm16, + SltiRxImmX16, SltiCCRxImmX16, + SltiuRxImm16, SltiuRxImmX16, SltiuCCRxImmX16, + SltRxRy16, SltCCRxRy16, SltuRxRy16, + SltuRxRyRz16, SltuCCRxRy16, SravRxRy16, + SraX16, SrlvRxRy16, SrlX16, SubuRxRyRz16, + XorRxRxRy16)>; + +def : InstRW<[GenericWriteALU], (instrs Constant32, LwConstant32, + GotPrologue16, CONSTPOOL_ENTRY)>; + +// microMIPS +// ========= + +def : InstRW<[GenericWriteALU], (instrs ADDIUPC_MM, ADDIUR1SP_MM, ADDIUR2_MM, + ADDIUS5_MM, ADDIUSP_MM, ADDU16_MM, ADD_MM, + ADDi_MM, ADDiu_MM, ADDu_MM, AND16_MM, + ANDI16_MM, AND_MM, ANDi_MM, CLO_MM, CLZ_MM, + EXT_MM, INS_MM, LEA_ADDiu_MM, LI16_MM, + LUi_MM, MOVE16_MM, MOVEP_MM, NOR_MM, + NOT16_MM, OR16_MM, OR_MM, ORi_MM, ROTRV_MM, + ROTR_MM, SEB_MM, SEH_MM, SLL16_MM, SLLV_MM, + SLL_MM, SLT_MM, SLTi_MM, SLTiu_MM, SLTu_MM, + SRAV_MM, SRA_MM, SRL16_MM, SRLV_MM, SRL_MM, + SSNOP_MM, SUBU16_MM, SUB_MM, SUBu_MM, + WSBH_MM, XOR16_MM, XOR_MM, XORi_MM)>; + +// microMIPS32r6 +// ============= + +def : InstRW<[GenericWriteALU], (instrs ADDIUPC_MMR6, ADDIU_MMR6, ADDU16_MMR6, + ADDU_MMR6, ADD_MMR6, ALIGN_MMR6, ALUIPC_MMR6, + AND16_MMR6, ANDI16_MMR6, ANDI_MMR6, AND_MMR6, + AUIPC_MMR6, AUI_MMR6, BITSWAP_MMR6, CLO_MMR6, + CLZ_MMR6, EXT_MMR6, INS_MMR6, LI16_MMR6, + LSA_MMR6, LUI_MMR6, MOVE16_MMR6, NOR_MMR6, + NOT16_MMR6, OR16_MMR6, ORI_MMR6, OR_MMR6, + SELEQZ_MMR6, SELNEZ_MMR6, SLL16_MMR6, + SLL_MMR6, SRL16_MMR6, SSNOP_MMR6, SUBU16_MMR6, + SUBU_MMR6, SUB_MMR6, WSBH_MMR6, XOR16_MMR6, + XORI_MMR6, XOR_MMR6)>; + +// MIPS64 +// ====== + +def : InstRW<[GenericWriteALU], (instrs AND64, ANDi64, DEXT64_32, DSLL64_32, + ORi64, SEB64, SEH64, SLL64_32, SLL64_64, + SLT64, SLTi64, SLTiu64, SLTu64, XOR64, + XORi64)>; + +def : InstRW<[GenericWriteALU], (instrs DADD, DADDi, DADDiu, DADDu, DCLO, + DCLZ, DEXT, DEXTM, DEXTU, DINS, DINSM, DINSU, + DROTR, DROTR32, DROTRV, DSBH, DSHD, DSLL, + DSLL32, DSLLV, DSRA, DSRA32, DSRAV, DSRL, + DSRL32, DSRLV, DSUB, DSUBu, LEA_ADDiu64, + LUi64, NOR64, OR64)>; + +// MIPS64R6 +// ======== + +def : InstRW<[GenericWriteALU], (instrs DALIGN, DAHI, DATI, DAUI, DCLO_R6, + DCLZ_R6, DBITSWAP, DLSA, DLSA_R6, SELEQZ64, + SELNEZ64)>; + + def GenericMDU : ProcResource<1> { let BufferSize = 1; } def GenericIssueMDU : ProcResource<1> { let Super = GenericALU; } def GenericIssueDIV : ProcResource<1> { let Super = GenericMDU; } def GenericWriteHILO : SchedWriteRes<[GenericIssueMDU]>; def GenericWriteALULong : SchedWriteRes<[GenericIssueALU]> { let Latency = 5; } def GenericWriteMove : SchedWriteRes<[GenericIssueALU]> { let Latency = 2; } +def GenericWriteMul : SchedWriteRes<[GenericIssueMDU]> { let Latency = 4; } -def : ItinRW<[GenericWriteHILO], [II_MADD, II_MADDU, II_MSUB, II_MSUBU]>; +def : InstRW<[GenericWriteHILO], (instrs MADD, MADDU, MSUB, MSUBU)>; + +def : InstRW<[GenericWriteHILO], (instrs PseudoMADD_MM, PseudoMADDU_MM, + PseudoMSUB_MM, PseudoMSUBU_MM, + PseudoMULT_MM, PseudoMULTu_MM)>; + +def : InstRW<[GenericWriteHILO], (instrs PseudoMADD, PseudoMADDU, PseudoMSUB, + PseudoMSUBU, PseudoMULT, PseudoMULTu)>; def GenericWriteMDUtoGPR : SchedWriteRes<[GenericIssueMDU]> { let Latency = 5; } -def : ItinRW<[GenericWriteMDUtoGPR], [II_MUL]>; - def GenericWriteDIV : SchedWriteRes<[GenericIssueDIV]> { // Estimated worst case let Latency = 33; @@ -82,63 +168,105 @@ def GenericWriteDIVU : SchedWriteRes<[GenericIssueDIV]> { let ResourceCycles = [31]; } -def : ItinRW<[GenericWriteDIV], [II_DIV]>; +// mul +def : InstRW<[GenericWriteMDUtoGPR], (instrs MUL)>; -def : ItinRW<[GenericWriteDIVU], [II_DIVU]>; +// mult, multu +def : InstRW<[GenericWriteMul], (instrs MULT, MULTu)>; -// MIPS64 -// ====== +// div, sdiv +def : InstRW<[GenericWriteDIV], (instrs PseudoSDIV, SDIV)>; + +def : InstRW<[GenericWriteDIVU], (instrs PseudoUDIV, UDIV)>; + +// mfhi, mflo, movn, mthi, mtlo, rdwhr +def : InstRW<[GenericWriteALULong], (instrs MFHI, MFLO, PseudoMFHI, + PseudoMFLO)>; + +def : InstRW<[GenericWriteALULong], (instrs PseudoMFHI_MM, PseudoMFLO_MM)>; -def : ItinRW<[GenericWriteALU], [II_DADDIU, II_DADDU, II_DADDI, II_DADD, - II_DCLO, II_DCLZ, II_DROTR, II_DROTR32, - II_DROTRV, II_DSBH, II_DSHD, II_DSLL, - II_DSLL32, II_DSLLV, II_DSRA, II_DSRA32, - II_DSRAV, II_DSRL, II_DSRL32, II_DSRLV, - II_DSUBU, II_DSUB]>; +def : InstRW<[GenericWriteMove], (instrs MTHI, MTLO, RDHWR, PseudoMTLOHI)>; +def : InstRW<[GenericWriteMove], (instrs PseudoMTLOHI_MM)>; -def : ItinRW<[GenericWriteDIV], [II_DDIV]>; +def : InstRW<[GenericWriteALU], (instrs MOVN_I_I, MOVZ_I_I)>; -def : ItinRW<[GenericWriteDIVU], [II_DDIVU]>; +// MIPSR6 +// ====== -def : ItinRW<[GenericWriteMDUtoGPR], [II_DMUL]>; +// muh, muhu, mulu, mul +def : InstRW<[GenericWriteMul], (instrs MUH, MUHU, MULU, MUL_R6)>; + +// divu, udiv +def : InstRW<[GenericWriteDIV], (instrs MOD, MODU, DIV, DIVU)>; -def : ItinRW<[GenericWriteHILO], [II_DMULU, II_DMULT, II_DMULTU]>; // MIPS16e // ======= -def : ItinRW<[GenericWriteALU], [IIM16Alu, IIPseudo]>; +def : InstRW<[GenericWriteHILO], (instrs MultRxRy16, MultuRxRy16, + MultRxRyRz16, MultuRxRyRz16)>; + +def : InstRW<[GenericWriteDIV], (instrs DivRxRy16)>; + +def : InstRW<[GenericWriteDIVU], (instrs DivuRxRy16)>; // microMIPS // ========= -def : ItinRW<[GenericWriteALU], [II_MOVE, II_LI, II_NOT]>; +def : InstRW<[GenericWriteMul], (instrs MULT_MM, MULTu_MM, MADD_MM, MADDU_MM, + MSUB_MM, MSUBU_MM)>; -// MIPSR6 +def : InstRW<[GenericWriteALULong], (instrs MUL_MM)>; + +def : InstRW<[GenericWriteDIV], (instrs SDIV_MM, SDIV_MM_Pseudo)>; + +def : InstRW<[GenericWriteDIVU], (instrs UDIV_MM, UDIV_MM_Pseudo)>; + +def : InstRW<[GenericWriteMove], (instrs MFHI16_MM, MFLO16_MM, MOVF_I_MM, + MOVT_I_MM, MFHI_MM, MFLO_MM, MTHI_MM, + MTLO_MM)>; + +def : InstRW<[GenericWriteMove], (instrs RDHWR_MM)>; + +// microMIPS32r6 +// ============= + +def : InstRW<[GenericWriteMul], (instrs MUHU_MMR6, MUH_MMR6, MULU_MMR6, + MUL_MMR6)>; + +def : InstRW<[GenericWriteDIV], (instrs MODU_MMR6, MOD_MMR6, DIVU_MMR6, + DIV_MMR6)>; + +def : InstRW<[GenericWriteMove], (instrs RDHWR_MMR6)>; + +// MIPS64 // ====== -def GenericWriteMul : SchedWriteRes<[GenericIssueMDU]> { let Latency = 4; } -def : ItinRW<[GenericWriteMul], [II_MUH, II_MUHU, II_MULU]>; +def : InstRW<[GenericWriteHILO], (instrs DMULU, DMULT, DMULTu, PseudoDMULT, + PseudoDMULTu)>; + +def : InstRW<[GenericWriteDIV], (instrs DSDIV, PseudoDSDIV)>; + +def : InstRW<[GenericWriteDIVU], (instrs DUDIV, PseudoDUDIV)>; -def : ItinRW<[GenericWriteDIV], [II_MOD, II_MODU]>; +def : InstRW<[GenericWriteALULong], (instrs MFHI64, MFLO64, PseudoMFHI64, + PseudoMFLO64, PseudoMTLOHI64)>; + +def : InstRW<[GenericWriteMove], (instrs MTHI64, MTLO64, RDHWR64)>; + +// mov[zn] +def : InstRW<[GenericWriteALU], (instrs MOVN_I_I64, MOVN_I64_I, MOVN_I64_I64, + MOVZ_I_I64, MOVZ_I64_I, MOVZ_I64_I64)>; -def : ItinRW<[GenericWriteALU], [II_ADDIUPC, II_ALIGN, II_ALUIPC, II_AUI, - II_AUIPC, II_BITSWAP, II_LSA, II_SELCCZ]>; // MIPS64R6 // ======== -def : ItinRW<[GenericWriteALU], [II_DALIGN, II_DAHI, II_DATI, II_DAUI, - II_DBITSWAP, II_DLSA]>; +def : InstRW<[GenericWriteMDUtoGPR], (instrs DMUH, DMUHU, DMUL_R6)>; -def : ItinRW<[GenericWriteMDUtoGPR], [II_DMUH, II_DMUHU]>; -def : ItinRW<[GenericWriteDIV], [II_DMOD, II_DMODU]>; - -// clo, clz, di, mfhi, mflo -def : ItinRW<[GenericWriteALULong], [II_MFHI_MFLO]>; -def : ItinRW<[GenericWriteALU], [II_MOVN, II_MOVZ]>; -def : ItinRW<[GenericWriteMove], [II_MTHI_MTLO, II_RDHWR]>; +def : InstRW<[GenericWriteDIV], (instrs DDIV, DMOD)>; +def : InstRW<[GenericWriteDIVU], (instrs DDIVU, DMODU)>; // CTISTD Pipeline // --------------- @@ -155,31 +283,150 @@ def GenericWriteJumpAndLink : SchedWriteRes<[GenericIssueCTISTD]> { // b, beq, beql, bg[et]z, bl[et]z, bne, bnel, j, syscall, jal, bltzal, jalx, // jalr, jr.hb, jr, jalr.hb, jarlc, jialc -def : ItinRW<[GenericWriteJump], [II_B, II_BCC, II_BCCZ, II_BCCZAL, II_J, - II_JR, II_JR_HB, II_ERET, II_ERETNC, - II_DERET]>; +def : InstRW<[GenericWriteJump], (instrs B, BAL, BAL_BR, BEQ, BNE, BGTZ, BGEZ, + BLEZ, BLTZ, BLTZAL, J, JALX, JR, JR_HB, ERET, + ERet, ERETNC, DERET)>; + +def : InstRW<[GenericWriteJump], (instrs BEQL, BNEL, BGEZL, BGTZL, BLEZL, + BLTZL)>; -def : ItinRW<[GenericWriteJumpAndLink], [II_JAL, II_JALR, II_JALR_HB, - II_BC2CCZ]>; +def : InstRW<[GenericWriteJump], (instrs TAILCALL, TAILCALLREG, + TAILCALLREGHB, PseudoIndirectBranch, + PseudoIndirectHazardBranch, PseudoReturn, + RetRA)>; -def : ItinRW<[GenericWriteJump], [II_JRC, II_JRADDIUSP]>; +def : InstRW<[GenericWriteJumpAndLink], (instrs BGEZAL, JAL, JALR, JALR_HB, + JALRHBPseudo, JALRPseudo)>; + +def : InstRW<[GenericWriteJumpAndLink], (instrs BGEZALL, BLTZALL)>; + +def GenericWriteTrap : SchedWriteRes<[GenericIssueCTISTD]>; -def : ItinRW<[GenericWriteJumpAndLink], [II_BCCZALS, II_JALS, II_JALRS]>; +def : InstRW<[GenericWriteTrap], (instrs BREAK, SYSCALL, TEQ, TEQI, + TGE, TGEI, TGEIU, TGEU, TNE, + TNEI, TLT, TLTI, TLTU, TTLTIU, + TRAP, SDBBP)>; // MIPSR6 // ====== -def : ItinRW<[GenericWriteJumpAndLink], [II_BALC, II_JALRC, II_JIALC]>; +def : InstRW<[GenericWriteJumpAndLink], (instrs BALC, BEQZALC, BGEZALC, + BGTZALC, BLEZALC, BLTZALC, + BNEZALC, + JIALC)>; -def : ItinRW<[GenericWriteJump], [II_JIC, II_BC, II_BCCC, II_BCCZC]>; +def : InstRW<[GenericWriteJump], (instrs BC, BC2EQZ, BC2NEZ, BEQC, BEQZC, BGEC, + BGEUC, BGEZC, BGTZC, BLEZC, BLTC, BLTUC, + BLTZC, BNEC, BNEZC, BNVC, BOVC, JIC, JR_HB_R6, + SIGRIE, PseudoIndirectBranchR6, + PseudoIndrectHazardBranchR6)>; +def : InstRW<[GenericWriteJump], (instrs TAILCALLR6REG, TAILCALLHBR6REG)>; -def GenericWriteTrap : SchedWriteRes<[GenericIssueCTISTD]>; +def : InstRW<[GenericWriteTrap], (instrs SDBBP_R6)>; + +// MIPS16e +// ======= + +def : InstRW<[GenericWriteJump], (instrs Bimm16, BimmX16, BeqzRxImm16, + BeqzRxImmX16, BnezRxImm16, BnezRxImmX16, + Bteqz16, BteqzX16, BteqzT8CmpX16, + BteqzT8CmpiX16, BteqzT8SltX16, + BteqzT8SltuX16, BteqzT8SltiX16, + BteqzT8SltiuX16, Btnez16, BtnezX16, + BtnezT8CmpX16, BtnezT8CmpiX16, + BtnezT8SltX16, BtnezT8SltuX16, + BtnezT8SltiX16, BtnezT8SltiuX16, JrRa16, + JrcRa16, JrcRx16, RetRA16)>; + +def : InstRW<[GenericWriteJumpAndLink], (instrs Jal16, JalB16, JumpLinkReg16)>; + +def : InstRW<[GenericWriteTrap], (instrs Break16)>; + +def : InstRW<[GenericWriteALULong], (instrs SelBeqZ, SelTBteqZCmp, + SelTBteqZCmpi, SelTBteqZSlt, + SelTBteqZSlti, SelTBteqZSltu, + SelTBteqZSltiu, SelBneZ, SelTBtneZCmp, + SelTBtneZCmpi, SelTBtneZSlt, + SelTBtneZSlti, SelTBtneZSltu, + SelTBtneZSltiu)>; + +// microMIPS +// ========= + +def : InstRW<[GenericWriteJump], (instrs B16_MM, BAL_BR_MM, BC1F_MM, BC1T_MM, + BEQZ16_MM, BEQZC_MM, BEQ_MM, BGEZ_MM, + BGTZ_MM, BLEZ_MM, BLTZ_MM, BNEZ16_MM, + BNEZC_MM, BNE_MM, B_MM, DERET_MM, ERET_MM, + JR16_MM, JR_MM, J_MM, B_MM_Pseudo)>; + +def : InstRW<[GenericWriteJumpAndLink], (instrs BGEZALS_MM, BGEZAL_MM, + BLTZALS_MM, BLTZAL_MM, JALR16_MM, + JALRS16_MM, JALRS_MM, JALR_MM, + JALS_MM, JALX_MM, JAL_MM)>; + +def : InstRW<[GenericWriteJump], (instrs TAILCALLREG_MM, TAILCALL_MM, + PseudoIndirectBranch_MM)>; + +def : InstRW<[GenericWriteTrap], (instrs BREAK16_MM, BREAK_MM, SDBBP16_MM, + SDBBP_MM, SYSCALL_MM, TEQI_MM, TEQ_MM, + TGEIU_MM, TGEI_MM, TGEU_MM, TGE_MM, TLTIU_MM, + TLTI_MM, TLTU_MM, TLT_MM, TNEI_MM, TNE_MM, + TRAP_MM)>; + +// microMIPS32r6 +// ============= + +def : InstRW<[GenericWriteJump], (instrs BC16_MMR6, BC1EQZC_MMR6, BC1NEZC_MMR6, + BC2EQZC_MMR6, BC2NEZC_MMR6, BC_MMR6, + BEQC_MMR6, BEQZC16_MMR6, BEQZC_MMR6, + BGEC_MMR6, BGEUC_MMR6, BGEZC_MMR6, + BGTZC_MMR6, BLEZC_MMR6, BLTC_MMR6, + BLTUC_MMR6, BLTZC_MMR6, BNEC_MMR6, + BNEZC16_MMR6, BNEZC_MMR6, BNVC_MMR6, + BOVC_MMR6, DERET_MMR6, ERETNC_MMR6, JAL_MMR6, + ERET_MMR6, JIC_MMR6, JRADDIUSP, JRC16_MM, + JRC16_MMR6, JRCADDIUSP_MMR6, SIGRIE_MMR6, + B_MMR6_Pseudo, PseudoIndirectBranch_MMR6)>; + +def : InstRW<[GenericWriteJumpAndLink], (instrs BALC_MMR6, BEQZALC_MMR6, + BGEZALC_MMR6, BGTZALC_MMR6, + BLEZALC_MMR6, BLTZALC_MMR6, + BNEZALC_MMR6, JALRC16_MMR6, + JALRC_HB_MMR6, JALRC_MMR6, + JIALC_MMR6)>; + +def : InstRW<[GenericWriteJump], (instrs TAILCALLREG_MMR6, TAILCALL_MMR6)>; + +def : InstRW<[GenericWriteTrap], (instrs BREAK16_MMR6, BREAK_MMR6, SDBBP_MMR6, + SDBBP16_MMR6)>; + +// MIPS64 +// ====== + +def : InstRW<[GenericWriteJump], (instrs BEQ64, BGEZ64, BGTZ64, BLEZ64, + BLTZ64, BNE64, JR64)>; + +def : InstRW<[GenericWriteJumpAndLink], (instrs JALR64, JALR64Pseudo, + JALRHB64Pseudo, JALR_HB64)>; + +def : InstRW<[GenericWriteJump], (instrs JR_HB64, TAILCALLREG64, + TAILCALLREGHB64, PseudoReturn64)>; + +// MIPS64R6 +// ======== + +def : InstRW<[GenericWriteJump], (instrs BEQC64, BEQZC64, BGEC64, BGEUC64, + BGEZC64, BGTZC64, BLEZC64, BLTC64, BLTUC64, + BLTZC64, BNEC64, BNEZC64, JIC64, + PseudoIndirectBranch64, + PseudoIndirectHazardBranch64)>; + +def : InstRW<[GenericWriteJumpAndLink], (instrs JIALC64)>; -def : ItinRW<[GenericWriteTrap], [II_BREAK, II_SYSCALL, II_TEQ, II_TEQI, - II_TGE, II_TGEI, II_TGEIU, II_TGEU, II_TNE, - II_TNEI, II_TLT, II_TLTI, II_TLTU, II_TTLTIU, - II_TRAP, II_SDBBP, II_SIGRIE]>; +def : InstRW<[GenericWriteJump], (instrs JR_HB64_R6, TAILCALL64R6REG, + TAILCALLHB64R6REG, PseudoIndirectBranch64R6, + PseudoIndrectHazardBranch64R6)>; // COP0 Pipeline // ============= @@ -196,35 +443,100 @@ def GenericReadWriteCOP0Long : SchedWriteRes<[GenericIssueCOP0]> { } def GenericWriteCOP0Short : SchedWriteRes<[GenericIssueCOP0]>; -def : ItinRW<[GenericWriteCOP0TLB], [II_TLBP, II_TLBR, II_TLBWI, II_TLBWR]>; -def : ItinRW<[GenericWriteCOP0TLB], [II_TLBINV, II_TLBINVF]>; +def : InstRW<[GenericWriteCOP0TLB], (instrs TLBP, TLBR, TLBWI, TLBWR)>; +def : InstRW<[GenericWriteCOP0TLB], (instrs TLBINV, TLBINVF)>; -def : ItinRW<[GenericReadCOP0], [II_MFC0]>; -def : ItinRW<[GenericWriteCOP0], [II_MTC0]>; +def : InstRW<[GenericReadCOP0], (instrs MFC0)>; +def : InstRW<[GenericWriteCOP0], (instrs MTC0)>; -def : ItinRW<[GenericWriteCOP0], [II_EVP, II_DVP]>; +def : InstRW<[GenericWriteCOP0], (instrs EVP, DVP)>; -// MIPSR5 -// ====== -def : ItinRW<[GenericReadCOP0], [II_MFHC0]>; -def : ItinRW<[GenericWriteCOP0], [II_MTHC0]>; +def : InstRW<[GenericWriteCOP0], (instrs DI, EI)>; + +def : InstRW<[GenericWriteCOP0], (instrs EHB, PAUSE, WAIT)>; + +// microMIPS +// ========= + +def : InstRW<[GenericWriteCOP0TLB], (instrs TLBP_MM, TLBR_MM, TLBWI_MM, + TLBWR_MM)>; + +def : InstRW<[GenericWriteCOP0], (instrs DI_MM, EI_MM)>; + +def : InstRW<[GenericWriteCOP0], (instrs EHB_MM, PAUSE_MM, WAIT_MM)>; + + +// microMIPS32R6 +// ============= + +def : InstRW<[GenericWriteCOP0], (instrs RDPGPR_MMR6, WRPGPR_MMR6)>; + +def : InstRW<[GenericWriteCOP0TLB], (instrs TLBINV_MMR6, TLBINVF_MMR6)>; + +def : InstRW<[GenericReadCOP0], (instrs MFHC0_MMR6, MFC0_MMR6, MFHC2_MMR6, + MFC2_MMR6)>; + +def : InstRW<[GenericWriteCOP0], (instrs MTHC0_MMR6, MTC0_MMR6, MTHC2_MMR6, + MTC2_MMR6)>; + +def : InstRW<[GenericWriteCOP0], (instrs EVP_MMR6, DVP_MMR6)>; + +def : InstRW<[GenericWriteCOP0], (instrs DI_MMR6, EI_MMR6)>; + +def : InstRW<[GenericWriteCOP0], (instrs EHB_MMR6, PAUSE_MMR6, WAIT_MMR6)>; // MIPS64 // ====== -def : ItinRW<[GenericReadCOP0], [II_DMFC0]>; -def : ItinRW<[GenericWriteCOP0], [II_DMTC0]>; +def : InstRW<[GenericReadCOP0], (instrs DMFC0)>; -def : ItinRW<[GenericWriteCOP0], [II_RDPGPR, II_WRPGPR]>; +def : InstRW<[GenericWriteCOP0], (instrs DMTC0)>; -def : ItinRW<[GenericWriteCOP0], [II_DI, II_EI]>; - -def : ItinRW<[GenericWriteCOP0], [II_EHB, II_PAUSE, II_WAIT]>; def GenericCOP2 : ProcResource<1> { let BufferSize = 1; } def GenericWriteCOPOther : SchedWriteRes<[GenericCOP2]>; -def : ItinRW<[GenericWriteCOPOther], [II_MFC2, II_MTC2, II_DMFC2, II_DMTC2]>; +def : InstRW<[GenericWriteCOPOther], (instrs MFC2, MTC2)>; + +def : InstRW<[GenericWriteCOPOther], (instrs DMFC2, DMTC2)>; + +// microMIPS32R6 +// ============= + +// The latency and repeat rate of these instructions are implementation +// dependant. +def : InstRW<[GenericWriteMove], (instrs CFC2_MM, CTC2_MM)>; + + +// MIPS MT ASE - hasMT +// ==================== + +def : InstRW<[GenericWriteMove], (instrs DMT, DVPE, EMT, EVPE, MFTR, + MTTR)>; + +def : InstRW<[GenericReadWriteCOP0Long], (instrs YIELD)>; + +def : InstRW<[GenericWriteCOP0Short], (instrs FORK)>; + +// MIPS Virtualization ASE +// ======================= + +def : InstRW<[GenericWriteCOP0Short], (instrs HYPCALL, TLBGINV, TLBGINVF, TLBGP, + TLBGR, TLBGWI, TLBGWR, MFGC0, MFHGC0, + MTGC0, MTHGC0)>; + +// MIPS64 Virtualization ASE +// ========================= + +def : InstRW<[GenericWriteCOP0Short], (instrs DMFGC0, DMTGC0)>; + +// microMIPS virtualization ASE +// ============================ + +def : InstRW<[GenericWriteCOP0Short], (instrs HYPCALL_MM, TLBGINVF_MM, + TLBGINV_MM, TLBGP_MM, TLBGR_MM, + TLBGWI_MM, TLBGWR_MM, MFGC0_MM, + MFHGC0_MM, MTGC0_MM, MTHGC0_MM)>; // LDST Pipeline // ------------- @@ -250,97 +562,168 @@ def GenericWriteLoadToOtherUnits : SchedWriteRes<[GenericIssueLDST]> { } // l[bhw], l[bh]u, ll -def : ItinRW<[GenericWriteLoad], [II_LB, II_LBU, II_LH, II_LHU, II_LW, II_LL, - II_LWC2, II_LWC3, II_LDC2, II_LDC3]>; +def : InstRW<[GenericWriteLoad], (instrs LB, LBu, LH, LHu, LW, LL, + LWC2, LWC3, LDC2, LDC3)>; // lw[lr] -def : ItinRW<[GenericWriteLoad], [II_LWL, II_LWR]>; +def : InstRW<[GenericWriteLoad], (instrs LWL, LWR)>; -// MIPS64 loads -def : ItinRW<[GenericWriteLoad], [II_LD, II_LLD, II_LWU]>; +// s[bhw], sc, s[dw]c[23] +def : InstRW<[GenericWriteStore], (instrs SB, SH, SW, SWC2, SWC3, + SDC2, SDC3)>; -// ld[lr] -def : ItinRW<[GenericWriteLoad], [II_LDL, II_LDR]>; +// PreMIPSR6 sw[lr] +def : InstRW<[GenericWriteStore], (instrs SWL, SWR)>; -// MIPS32 EVA -def : ItinRW<[GenericWriteLoad], [II_LBE, II_LBUE, II_LHE, II_LHUE, II_LWE, - II_LLE]>; +def : InstRW<[GenericWriteStoreSC], (instrs SC, SC_MMR6)>; -def : ItinRW<[GenericWriteLoad], [II_LWLE, II_LWRE]>; +// pref +def : InstRW<[GenericWritePref], (instrs PREF)>; +// cache +def : InstRW<[GenericWriteCache], (instrs CACHE)>; -// MIPS MT instructions -// ==================== +// sync +def : InstRW<[GenericWriteSync], (instrs SYNC, SYNCI)>; -def : ItinRW<[GenericWriteMove], [II_DMT, II_DVPE, II_EMT, II_EVPE, II_MFTR, - II_MTTR]>; +// MIPSR6 +// ====== -def : ItinRW<[GenericReadWriteCOP0Long], [II_YIELD]>; +def : InstRW<[GenericWriteLoad], (instrs LDC2_R6, LL_R6, LWC2_R6, LWPC)>; -def : ItinRW<[GenericWriteCOP0Short], [II_FORK]>; +def : InstRW<[GenericWriteStore], (instrs SWC2_R6, SDC2_R6)>; -// MIPS32R6 and MIPS16e -// ==================== +def : InstRW<[GenericWriteStoreSC], (instrs SC_R6)>; -def : ItinRW<[GenericWriteLoad], [II_LWPC]>; +def : InstRW<[GenericWritePref], (instrs PREF_R6)>; -// MIPS64R6 -// ==================== +def : InstRW<[GenericWriteCache], (instrs CACHE_R6)>; -def : ItinRW<[GenericWriteLoad], [II_LWUPC, II_LDPC]>; +def : InstRW<[GenericWriteSync], (instrs GINVI, GINVT)>; +// MIPS32 EVA +// ========== -// s[bhw], sc, s[dw]c[23] -def : ItinRW<[GenericWriteStore], [II_SB, II_SH, II_SW, II_SWC2, II_SWC3, - II_SDC2, II_SDC3]>; +def : InstRW<[GenericWriteLoad], (instrs LBE, LBuE, LHE, LHuE, LWE, + LLE)>; -def : ItinRW<[GenericWriteStoreSC], [II_SC]>; +def : InstRW<[GenericWriteStore], (instrs SBE, SHE, SWE, SCE)>; -// PreMIPSR6 sw[lr] -def : ItinRW<[GenericWriteStore], [II_SWL, II_SWR]>; +def : InstRW<[GenericWriteLoad], (instrs LWLE, LWRE)>; -// EVA ASE stores -def : ItinRW<[GenericWriteStore], [II_SBE, II_SHE, II_SWE, II_SCE]>; +def : InstRW<[GenericWriteStore], (instrs SWLE, SWRE)>; -def : ItinRW<[GenericWriteStore], [II_SWLE, II_SWRE]>; +def : InstRW<[GenericWritePref], (instrs PREFE)>; -// MIPS64 -// ====== +def : InstRW<[GenericWriteCache], (instrs CACHEE)>; + +// microMIPS EVA ASE - InMicroMipsMode, hasEVA +// =========================================== + +def : InstRW<[GenericWriteLoad], (instrs LBE_MM, LBuE_MM, LHE_MM, LHuE_MM, + LWE_MM, LWLE_MM, LWRE_MM, LLE_MM)>; -def : ItinRW<[GenericWriteStore], [II_SD, II_SCD]>; +def : InstRW<[GenericWriteStore], (instrs SBE_MM, SB_MM, SHE_MM, SWE_MM, + SWLE_MM, SWRE_MM, SCE_MM)>; -// PreMIPSR6 stores -// ================ +def : InstRW<[GenericWritePref], (instrs PREFE_MM)>; +def : InstRW<[GenericWriteCache], (instrs CACHEE_MM)>; -def : ItinRW<[GenericWriteStore], [II_SDL, II_SDR]>; // MIPS16e // ======= -def : ItinRW<[GenericWriteLoad], [II_RESTORE]>; +def : InstRW<[GenericWriteLoad], (instrs Restore16, RestoreX16, + LbRxRyOffMemX16, + LbuRxRyOffMemX16, LhRxRyOffMemX16, + LhuRxRyOffMemX16, LwRxRyOffMemX16, + LwRxSpImmX16, LwRxPcTcp16, LwRxPcTcpX16)>; -def : ItinRW<[GenericWriteStore], [II_SAVE]>; +def : InstRW<[GenericWriteStore], (instrs Save16, SaveX16, SbRxRyOffMemX16, + ShRxRyOffMemX16, SwRxRyOffMemX16, + SwRxSpImmX16)>; // microMIPS // ========= -def : ItinRW<[GenericWriteLoad], [II_LWM, II_LWP, II_LWXS]>; +def : InstRW<[GenericWriteLoad], (instrs LBU16_MM, LB_MM, LBu_MM, LHU16_MM, + LH_MM, LHu_MM, LL_MM, LW16_MM, LWGP_MM, + LWL_MM, LWM16_MM, LWM32_MM, LWP_MM, LWR_MM, + LWSP_MM, LWU_MM, LWXS_MM, LW_MM)>; -def : ItinRW<[GenericWriteStore], [II_SWM, II_SWP]>; +def : InstRW<[GenericWriteStore], (instrs SB16_MM, SC_MM, SH16_MM, SH_MM, + SW16_MM, SWL_MM, SWM16_MM, SWM32_MM, SWM_MM, + SWP_MM, SWR_MM, SWSP_MM, SW_MM)>; -// pref -def : ItinRW<[GenericWritePref], [II_PREF]>; -def : ItinRW<[GenericWritePref], [II_PREFE]>; +def : InstRW<[GenericWritePref], (instrs PREF_MM, PREFX_MM)>; -// cache -def : ItinRW<[GenericWriteCache], [II_CACHE]>; +def : InstRW<[GenericWriteCache], (instrs CACHE_MM)>; -def : ItinRW<[GenericWriteCache], [II_CACHEE]>; +def : InstRW<[GenericWriteSync], (instrs SYNC_MM, SYNCI_MM)>; +def : InstRW<[GenericWriteSync], (instrs GINVI_MMR6, GINVT_MMR6)>; -// sync -def : ItinRW<[GenericWriteSync], [II_SYNC]>; +// microMIPS32r6 +// ============= + +def : InstRW<[GenericWriteLoad], (instrs LBU_MMR6, LB_MMR6, LDC2_MMR6, LL_MMR6, + LWM16_MMR6, LWC2_MMR6, LWPC_MMR6, LW_MMR6)>; + +def : InstRW<[GenericWriteStore], (instrs SB16_MMR6, SB_MMR6, SDC2_MMR6, + SH16_MMR6, SH_MMR6, SW16_MMR6, SWC2_MMR6, + SWM16_MMR6, SWSP_MMR6, SW_MMR6)>; + +def : InstRW<[GenericWriteSync], (instrs SYNC_MMR6, SYNCI_MMR6)>; + +def : InstRW<[GenericWritePref], (instrs PREF_MMR6)>; -def : ItinRW<[GenericWriteSync], [II_SYNCI]>; +def : InstRW<[GenericWriteCache], (instrs CACHE_MMR6)>; + +// MIPS64 +// ====== + +def : InstRW<[GenericWriteLoad], (instrs LD, LL64, LLD, LWu, LB64, LBu64, + LH64, LHu64, LW64)>; + +// l[dw][lr] +def : InstRW<[GenericWriteLoad], (instrs LWL64, LWR64, LDL, LDR)>; + +def : InstRW<[GenericWriteStore], (instrs SD, SC64, SCD, SB64, SH64, SW64, + SWL64, SWR64)>; + +def : InstRW<[GenericWriteStore], (instrs SDL, SDR)>; + +// MIPS64R6 +// ======== + +def : InstRW<[GenericWriteLoad], (instrs LWUPC, LDPC)>; + +def : InstRW<[GenericWriteLoad], (instrs LLD_R6, LL64_R6)>; + +def : InstRW<[GenericWriteStoreSC], (instrs SC64_R6, SCD_R6)>; + +// MIPSR6 CRC ASE - hasCRC +// ======================= + +def : InstRW<[GenericWriteALU], (instrs CRC32B, CRC32H, CRC32W, CRC32CB, + CRC32CH, CRC32CW)>; + +// MIPS64R6 CRC ASE - hasCRC +// ------------------------- + +def : InstRW<[GenericWriteALU], (instrs CRC32D, CRC32CD)>; + + +// Cavium Networks MIPS (cnMIPS) - Octeon, HasCnMips +// ================================================= + +def : InstRW<[GenericWriteALU], (instrs BADDu, BBIT0, BBIT032, BBIT1, BBIT132, + CINS, CINS32, CINS64_32, CINS_i32, + DMFC2_OCTEON, DMTC2_OCTEON, DPOP, EXTS, + EXTS32, MTM0, MTM1, MTM2, MTP0, MTP1, MTP2, + POP, SEQ, SEQi, SNE, SNEi, V3MULU, VMM0, + VMULU)>; + +def : InstRW<[GenericWriteMDUtoGPR], (instrs DMUL)>; // FPU Pipelines // ============= @@ -408,10 +791,10 @@ def GenericWriteFPUSqrtD : SchedWriteRes<[GenericFPUDivSqrt]> { // --------------------------------- // // c.<cc>.[ds], bc1[tf], bc1[tf]l -def : ItinRW<[GenericWriteFPUCmp], [II_C_CC_D, II_C_CC_S, II_BC1F, II_BC1T, - II_BC1FL, II_BC1TL]>; +def : InstRW<[GenericWriteFPUCmp], (instrs FCMP_D32, FCMP_D64, FCMP_S32, BC1F, + BC1T, BC1FL, BC1TL)>; -def : ItinRW<[GenericWriteFPUCmp], [II_CMP_CC_D, II_CMP_CC_S]>; +def : InstRW<[GenericWriteFPUCmp], (instregex "C_[A-Z]+_(S|D32|D64)$")>; // Short Pipe // ---------- @@ -419,21 +802,10 @@ def : ItinRW<[GenericWriteFPUCmp], [II_CMP_CC_D, II_CMP_CC_S]>; // abs.[ds], abs.ps, add.[ds], neg.[ds], neg.ps, madd.s, msub.s, nmadd,s // nmsub.s, sub.[ds], mul.s -def : ItinRW<[GenericWriteFPUS], [II_ABS, II_ADD_D, II_ADD_S, II_MADD_S, - II_MSUB_S, II_MUL_S, II_NEG, II_NMADD_S, - II_NMSUB_S, II_SUB_S, II_SUB_D]>; -// mov[tf].[ds] - -def : ItinRW<[GenericWriteFPUS], [II_MOVF_S, II_MOVF_D, II_MOVT_S, II_MOVT_D]>; - -// MIPSR6 -// ------ -// -// sel(eq|ne).[ds], max.[ds], maxa.[ds], min.[ds], mina.[ds], class.[ds] -def : ItinRW<[GenericWriteFPUS], [II_SELCCZ_S, II_SELCCZ_D, II_MAX_S, - II_MAX_D, II_MAXA_S, II_MAXA_D, II_MIN_S, - II_MIN_D, II_MINA_S, II_MINA_D, II_CLASS_S, - II_CLASS_D]>; +def : InstRW<[GenericWriteFPUS], (instrs FABS_S, FABS_D32, FABS_D64, FADD_D32, + FADD_D64, FADD_S, MADD_S, MSUB_S, FMUL_S, + FNEG_S, FNEG_D32, FNEG_D64, NMADD_S, NMSUB_S, + FSUB_S, FSUB_D32, FSUB_D64)>; // Long Pipe // ---------- @@ -445,71 +817,211 @@ def : ItinRW<[GenericWriteFPUS], [II_SELCCZ_S, II_SELCCZ_D, II_MAX_S, // madd.d, msub.dm mul.d, mul.ps, nmadd.d, nmsub.d, ceil.[wl].[sd], cvt.d.[sw], // cvt.s.[dw], cvt.w.[sd], cvt.[sw].ps, round.[lw].[ds], floor.[lw].ds, // trunc.w.[ds], trunc.w.ps, -def : ItinRW<[GenericWriteFPUL], [II_MADD_D, II_MSUB_D, II_MUL_D, II_NMADD_D, - II_NMSUB_D, II_CEIL, II_CVT, - II_FLOOR, II_ROUND, II_TRUNC]>; +def : InstRW<[GenericWriteFPUL], (instrs CEIL_L_D64, CEIL_L_S, CEIL_W_D32, + CEIL_W_D64, CEIL_W_S, CVT_D32_S, CVT_D32_W, + CVT_D64_L, CVT_D64_S, CVT_D64_W, CVT_L_D64, + CVT_L_S, CVT_S_D32, CVT_S_D64, CVT_S_L, + CVT_S_W, CVT_W_D32, CVT_W_D64, CVT_W_S, + CVT_PS_S64, CVT_S_PL64, CVT_S_PU64, + FLOOR_L_D64, FLOOR_L_S, FLOOR_W_D32, + FLOOR_W_D64, FLOOR_W_S, FMUL_D32, FMUL_D64, + MADD_D32, MADD_D64, MSUB_D32, MSUB_D64, + NMADD_D32, NMADD_D64, NMSUB_D32, NMSUB_D64, + PLL_PS64, PLU_PS64, + ROUND_L_D64, ROUND_L_S, ROUND_W_D32, + ROUND_W_D64, ROUND_W_S, TRUNC_L_D64, + TRUNC_L_S, TRUNC_W_D32, TRUNC_W_D64, + TRUNC_W_S, PseudoTRUNC_W_D, + PseudoTRUNC_W_D32, PseudoTRUNC_W_S)>; + +// Pseudo convert instruction +def : InstRW<[GenericWriteFPUL], (instrs PseudoCVT_D32_W, PseudoCVT_D64_L, + PseudoCVT_D64_W, PseudoCVT_S_L, + PseudoCVT_S_W)>; // div.[ds], div.ps -def : ItinRW<[GenericWriteFPUDivS], [II_DIV_S]>; -def : ItinRW<[GenericWriteFPUDivD], [II_DIV_D]>; +def : InstRW<[GenericWriteFPUDivS], (instrs FDIV_S)>; +def : InstRW<[GenericWriteFPUDivD], (instrs FDIV_D32, FDIV_D64)>; // sqrt.[ds], sqrt.ps -def : ItinRW<[GenericWriteFPUSqrtS], [II_SQRT_S]>; -def : ItinRW<[GenericWriteFPUSqrtD], [II_SQRT_D]>; +def : InstRW<[GenericWriteFPUSqrtS], (instrs FSQRT_S)>; +def : InstRW<[GenericWriteFPUSqrtD], (instrs FSQRT_D32, FSQRT_D64)>; // rsqrt.[ds], recip.[ds] -def : ItinRW<[GenericWriteFPURcpS], [II_RECIP_S, II_RSQRT_S]>; -def : ItinRW<[GenericWriteFPURcpD], [II_RECIP_D, II_RSQRT_D]>; +def : InstRW<[GenericWriteFPURcpS], (instrs RECIP_S, RSQRT_S)>; +def : InstRW<[GenericWriteFPURcpD], (instrs RECIP_D32, RECIP_D64, + RSQRT_D32, RSQRT_D64)>; -// MIPSR6 -// ====== -// -// rint.[ds] -def : ItinRW<[GenericWriteFPUL], [II_RINT_S, II_RINT_D]>; // Load Pipe // --------- // ctc1, mtc1, mthc1, cfc1, mfc1, mfhc1 -def : ItinRW<[GenericWriteFPUMoveGPRFPU], [II_CFC1, II_CTC1, II_MFC1, II_MFHC1, - II_MTC1, II_MTHC1]>; +def : InstRW<[GenericWriteFPUMoveGPRFPU], (instrs BuildPairF64, + BuildPairF64_64, ExtractElementF64, + ExtractElementF64_64, CFC1, CTC1, + MFC1, MFC1_D64, MFHC1_D32, + MFHC1_D64, MTC1, MTC1_D64, + MTHC1_D32, MTHC1_D64)>; // swc1, swxc1 -def : ItinRW<[GenericWriteFPUStore], [II_SDC1, II_SDXC1, II_SUXC1, II_SWC1, - II_SWXC1]>; +def : InstRW<[GenericWriteFPUStore], (instrs SDC1, SDC164, SDXC1, SDXC164, + SUXC1, SUXC164, SWC1, SWXC1)>; + +def : InstRW<[GenericWriteFPUMoveFP], (instrs FMOV_D32, FMOV_D64, FMOV_S)>; + // movn.[ds], movz.[ds] -def : ItinRW<[GenericWriteFPUMoveFP], [II_MOV_D, II_MOV_S, II_MOVF, II_MOVT, - II_MOVN_D, II_MOVN_S, II_MOVZ_D, - II_MOVZ_S]>; +def : InstRW<[GenericWriteFPUMoveFP], (instrs MOVF_I, MOVF_D32, MOVF_D64, + MOVF_S, MOVT_I, MOVT_D32, MOVT_D64, + MOVT_S, MOVN_I_D32, MOVN_I_D64, + MOVN_I_S, MOVZ_I_D32, MOVZ_I_D64, + MOVZ_I_S)>; + +def : InstRW<[GenericWriteFPUMoveFP], (instrs MOVT_I64, MOVF_I64, MOVZ_I64_S, + MOVN_I64_D64, MOVN_I64_S, + MOVZ_I64_D64)>; // l[dw]x?c1 -def : ItinRW<[GenericWriteFPULoad], [II_LDC1, II_LDXC1, II_LUXC1, II_LWC1, - II_LWXC1]>; +def : InstRW<[GenericWriteFPULoad], (instrs LDC1, LDC164, LDXC1, LDXC164, + LUXC1, LUXC164, LWC1, LWXC1)>; -// MIPS64 +// MIPSR6 // ====== -def : ItinRW<[GenericWriteFPUMoveGPRFPU], [II_DMFC1, II_DMTC1]>; +// sel(eq|ne).[ds], max.[ds], maxa.[ds], min.[ds], mina.[ds], class.[ds] +def : InstRW<[GenericWriteFPUS], (instrs SELEQZ_S, SELNEZ_S, SELEQZ_D, SELNEZ_D, + MAX_S, MAX_D, MAXA_S, MAXA_D, MIN_S, MIN_D, + MINA_S, MINA_D, CLASS_S, CLASS_D)>; -// MIPSR6 -// ====== +def : InstRW<[GenericWriteFPUL], (instrs RINT_S, RINT_D)>; -def : ItinRW<[GenericWriteFPUS], [II_MADDF_S, II_MSUBF_S]>; +def : InstRW<[GenericWriteFPUCmp], (instrs BC1EQZ, BC1NEZ, SEL_D, SEL_S)>; -def : ItinRW<[GenericWriteFPUS], [II_MADDF_D, II_MSUBF_D]>; +def : InstRW<[GenericWriteFPUS], (instrs MADDF_S, MSUBF_S, MADDF_D, MSUBF_D)>; -def : ItinRW<[GenericWriteFPUCmp], [II_BC1CCZ, II_SEL_D, II_SEL_S]>; -// Cavium Networks MIPS (cnMIPS) - Octeon, HasCnMips -// ================================================= +// microMIPS +// ========= + +def : InstRW<[GenericWriteFPUMoveFP], (instrs MOVF_D32_MM, MOVF_S_MM, + MOVN_I_D32_MM, MOVN_I_S_MM, + MOVT_D32_MM, MOVT_S_MM, MOVZ_I_D32_MM, + MOVZ_I_S_MM)>; + + +// cvt.?.?, ceil.?, floor.?, round.?, trunc.? (n)madd.? (n)msub.? +def : InstRW<[GenericWriteFPUL], (instrs CVT_D32_S_MM, CVT_D32_W_MM, + CVT_D64_S_MM, CVT_D64_W_MM, CVT_L_D64_MM, + CVT_L_S_MM, CVT_S_D32_MM, CVT_S_D64_MM, + CVT_S_W_MM, CVT_W_D32_MM, CVT_W_D64_MM, + CVT_W_S_MM, CEIL_W_MM, CEIL_W_S_MM, + FLOOR_W_MM, FLOOR_W_S_MM, NMADD_S_MM, + NMADD_D32_MM, NMSUB_S_MM, NMSUB_D32_MM, + MADD_S_MM, MADD_D32_MM, ROUND_W_MM, + ROUND_W_S_MM, TRUNC_W_MM, TRUNC_W_S_MM)>; + +def : InstRW<[GenericWriteFPUCmp], (instregex "^C_[A-Z]_(S|D32|D64)_MM$")>; +def : InstRW<[GenericWriteFPUCmp], (instregex "^C_[A-Z][A-Z]_(S|D32|D64)_MM$")>; +def : InstRW<[GenericWriteFPUCmp], (instregex "^C_[A-Z][A-Z][A-Z]_(S|D32|D64)_MM$")>; +def : InstRW<[GenericWriteFPUCmp], (instregex "^C_NGLE_(S|D32|D64)_MM$")>; +def : InstRW<[GenericWriteFPUCmp], (instrs FCMP_S32_MM, FCMP_D32_MM)>; + +def : InstRW<[GenericWriteFPUS], (instrs MFC1_MM, MFHC1_D32_MM, MFHC1_D64_MM, + MTC1_MM, MTC1_D64_MM, + MTHC1_D32_MM, MTHC1_D64_MM)>; + +def : InstRW<[GenericWriteFPUS], (instrs FABS_D32_MM, FABS_D64_MM, FABS_S_MM, + FNEG_D32_MM, FNEG_D64_MM, FNEG_S_MM, + FADD_D32_MM, FADD_D64_MM, FADD_S_MM, + FMOV_D32_MM, FMOV_D64_MM, FMOV_S_MM, + FMUL_D32_MM, FMUL_D64_MM, FMUL_S_MM, + FSUB_D32_MM, FSUB_D64_MM, FSUB_S_MM, + MSUB_S_MM, MSUB_D32_MM)>; + +def : InstRW<[GenericWriteFPUDivS], (instrs FDIV_S_MM)>; +def : InstRW<[GenericWriteFPUDivD], (instrs FDIV_D32_MM, FDIV_D64_MM)>; + +def : InstRW<[GenericWriteFPUSqrtS], (instrs FSQRT_S_MM)>; +def : InstRW<[GenericWriteFPUSqrtD], (instrs FSQRT_D32_MM, FSQRT_D64_MM)>; + +def : InstRW<[GenericWriteFPURcpS], (instrs RECIP_S_MM, RSQRT_S_MM)>; +def : InstRW<[GenericWriteFPURcpD], (instrs RECIP_D32_MM, RECIP_D64_MM, + RSQRT_D32_MM, RSQRT_D64_MM)>; + +def : InstRW<[GenericWriteFPUStore], (instrs SDC1_MM, SWC1_MM, SUXC1_MM, + SWXC1_MM)>; + +def : InstRW<[GenericWriteFPUMoveGPRFPU], (instrs CFC1_MM, CTC1_MM)>; + +def : InstRW<[GenericWriteFPULoad], (instrs LDC1_MM, LUXC1_MM, LWC1_MM, + LWXC1_MM)>; + +// microMIPS32r6 +// ============= + +def : InstRW<[GenericWriteFPUS], (instrs FNEG_S_MMR6)>; + +def : InstRW<[GenericWriteFPUCmp], (instregex "CMP_[A-Z][A-Z]_(S|D)_MMR6")>; +def : InstRW<[GenericWriteFPUCmp], + (instregex "CMP_[A-Z][A-Z][A-Z]_(S|D)_MMR6")>; +def : InstRW<[GenericWriteFPUCmp], + (instregex "CMP_[A-Z][A-Z][A-Z][A-Z]_(S|D)_MMR6")>; + +def : InstRW<[GenericWriteFPUL], + (instregex "CVT_(L|D|S|W)_(L|D|S|L|W)_MMR6")>; + +def : InstRW<[GenericWriteFPUL], + (instregex "TRUNC_(L|W)_(D|S)_MMR6")>; + +def : InstRW<[GenericWriteFPUL], + (instregex "ROUND_(L|W)_(D|S)_MMR6")>; -def : ItinRW<[GenericWriteALU], [II_SEQ_SNE, II_SEQI_SNEI, II_POP, II_BADDU, - II_BBIT]>; +def : InstRW<[GenericWriteFPUL], + (instregex "FLOOR_(L|W)_(D|S)_MMR6")>; + +def : InstRW<[GenericWriteFPUL], + (instregex "CEIL_(L|W)_(S|D)_MMR6")>; + +def : InstRW<[GenericWriteFPUS], + (instrs MFC1_MMR6, MTC1_MMR6, CLASS_S_MMR6, CLASS_D_MMR6, + FADD_S_MMR6)>; + +def : InstRW<[GenericWriteFPUS], (instregex "M(IN|AX)_(S|D)_MMR6")>; + +def : InstRW<[GenericWriteFPUS], (instregex "M(IN|AX)A_(S|D)_MMR6")>; + +def : InstRW<[GenericWriteFPUS], (instregex "SEL(EQ|NE)Z_(S|D)_MMR6")>; + +def : InstRW<[GenericWriteFPUS], (instregex "SEL_(S|D)_MMR6")>; + +def : InstRW<[GenericWriteFPUL], (instrs RINT_S_MMR6, RINT_D_MMR6)>; + +def : InstRW<[GenericWriteFPUS], (instregex "M(ADD|SUB)F_(S|D)_MMR6")>; + +def : InstRW<[GenericWriteFPUS], (instrs FMOV_S_MMR6, FMUL_S_MMR6, + FSUB_S_MMR6, FMOV_D_MMR6)>; + +def : InstRW<[GenericWriteFPUL], (instrs FDIV_S_MMR6)>; + +def : InstRW<[GenericWriteFPUStore], (instrs SDC1_D64_MMR6)>; + +def : InstRW<[GenericWriteFPULoad], (instrs LDC1_D64_MMR6)>; + +// MIPS64 +// ====== + +def : InstRW<[GenericWriteFPUMoveGPRFPU], (instrs DMFC1, DMTC1)>; // MIPS DSP ASE, HasDSP // ==================== +def : InstRW<[GenericWriteStore], (instrs SWDSP)>; + +def : InstRW<[GenericWriteLoad], (instrs LWDSP)>; + +def : InstRW<[GenericWriteMove], (instrs PseudoMTLOHI_DSP)>; + def GenericDSP : ProcResource<1> { let BufferSize = 1; } def GenericDSPShort : SchedWriteRes<[GenericDSP]> { let Latency = 2; } def GenericDSPLong : SchedWriteRes<[GenericDSP]> { let Latency = 6; } @@ -634,6 +1146,11 @@ def : InstRW<[GenericDSPShort], (instregex "^SUBU_QB$")>; def : InstRW<[GenericDSPShort], (instregex "^SUBU_S_QB$")>; def : InstRW<[GenericDSPShort], (instregex "^WRDSP$")>; +def : InstRW<[GenericDSPShort], + (instregex "^Pseudo(CMP|CMPU)_(EQ|LE|LT)_(PH|QB)$")>; +def : InstRW<[GenericDSPShort], + (instregex "^PseudoPICK_(PH|QB)$")>; + // MIPS DSP R2 - hasDSP, HasDSPR2, InMicroMips // =========================================== @@ -687,6 +1204,10 @@ def : InstRW<[GenericDSPShort], (instregex "^SUBUH_R_QB$")>; // microMIPS DSP R1 - HasDSP, InMicroMips // ====================================== +def : InstRW<[GenericWriteLoad], (instrs LWDSP_MM)>; + +def : InstRW<[GenericWriteStore], (instrs SWDSP_MM)>; + def : InstRW<[GenericDSPShort], (instregex "^ABSQ_S_PH_MM$")>; def : InstRW<[GenericDSPShort], (instregex "^ABSQ_S_W_MM$")>; def : InstRW<[GenericDSPShort], (instregex "^ADDQ_PH_MM$")>; @@ -740,7 +1261,6 @@ def : InstRW<[GenericDSPShort], (instregex "^MAQ_S_W_PHR_MM$")>; def : InstRW<[GenericDSPShort], (instregex "^MFHI_DSP_MM$")>; def : InstRW<[GenericDSPShort], (instregex "^MFLO_DSP_MM$")>; def : InstRW<[GenericDSPShort], (instregex "^MODSUB_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^MOVEP_MM$")>; def : InstRW<[GenericDSPShort], (instregex "^MOVEP_MMR6$")>; def : InstRW<[GenericDSPShort], (instregex "^MOVN_I_MM$")>; def : InstRW<[GenericDSPShort], (instregex "^MOVZ_I_MM$")>; @@ -902,12 +1422,14 @@ def : InstRW<[GenericWriteMSAShortInt], (instregex "^ADDVI?_[BHWD]$")>; def : InstRW<[GenericWriteMSAShortInt], (instregex "^ASUB_[US].[BHWD]$")>; def : InstRW<[GenericWriteMSAShortInt], (instregex "^AVER?_[US].[BHWD]$")>; -// and.v, andi.b, move.v, ldi.[bhwd], xor.v, nor.v, xori.b, nori.b +// and.v, andi.b, move.v, ldi.[bhwd], xor.v, nor.v, xori.b, nori.b, lsa def : InstRW<[GenericWriteMSAShortLogic], (instregex "^MOVE_V$")>; def : InstRW<[GenericWriteMSAShortLogic], (instregex "^LDI_[BHWD]$")>; +def : InstRW<[GenericWriteMSAShortLogic], (instrs LSA)>; def : InstRW<[GenericWriteMSAShortLogic], (instregex "^(AND|OR|[XN]OR)_V$")>; def : InstRW<[GenericWriteMSAShortLogic], (instregex "^(AND|OR|[XN]OR)I_B$")>; -def : InstRW<[GenericWriteMSAShortLogic], (instregex "^(AND|OR|[XN]OR)I_B$")>; +def : InstRW<[GenericWriteMSAShortLogic], + (instregex "^(AND|OR|[XN]OR)_V_[DHW]_PSEUDO$")>; // vshf.[bhwd], binsl.[bhwd], binsr.[bhwd], insert.[bhwd], sld?.[bhwd], // bset.[bhwd], bclr.[bhwd], bneg.[bhwd], bsel_v, bseli_b @@ -921,8 +1443,10 @@ def : InstRW<[GenericWriteMSAShortInt], (instregex "^(BCLR|BCLRI)_[BHWD]$")>; def : InstRW<[GenericWriteMSAShortInt], (instregex "^(BNEG|BNEGI)_[BHWD]$")>; def : InstRW<[GenericWriteMSAShortInt], (instregex "^(BSEL_V|BSELI_B)$")>; def : InstRW<[GenericWriteMSAShortInt], (instregex "^BMN*Z.*$")>; +def : InstRW<[GenericWriteMSAShortInt], + (instregex "^BSEL_(H|W|D|FW|FD)_PSEUDO$")>; -// pcnt.[bhwd], sat_s.[bhwd], sat_u.bhwd] +// pcnt.[bhwd], sat_s.[bhwd], sat_u.[bhwd] def : InstRW<[GenericWriteMSAOther3], (instregex "^PCNT_[BHWD]$")>; def : InstRW<[GenericWriteMSAOther3], (instregex "^SAT_(S|U)_[BHWD]$")>; @@ -935,10 +1459,6 @@ def : InstRW<[GenericWriteMSAShortInt], (instregex "^SHF_[BHW]$")>; def : InstRW<[GenericWriteMSAShortInt], (instregex "^FILL_[BHWD]$")>; def : InstRW<[GenericWriteMSAShortInt], (instregex "^(SPLAT|SPLATI)_[BHWD]$")>; -// pcnt.[bhwd], sat_s.[bhwd], sat_u.bhwd] -def : InstRW<[GenericWriteMSAOther3], (instregex "^PCNT_[BHWD]$")>; -def : InstRW<[GenericWriteMSAOther3], (instregex "^SAT_(S|U)_[BHWD]$")>; - // fexp2_w, fexp2_d def : InstRW<[GenericWriteFPUS], (instregex "^FEXP2_(W|D)$")>; @@ -953,6 +1473,15 @@ def : InstRW<[GenericWriteFPUS], (instregex "^CMP_LT_(S|D)$")>; def : InstRW<[GenericWriteFPUS], (instregex "^CMP_ULT_(S|D)$")>; def : InstRW<[GenericWriteFPUS], (instregex "^CMP_LE_(S|D)$")>; def : InstRW<[GenericWriteFPUS], (instregex "^CMP_ULE_(S|D)$")>; +def : InstRW<[GenericWriteFPUS], (instregex "^CMP_F_(D|S)$")>; +def : InstRW<[GenericWriteFPUS], (instregex "^CMP_SAF_(D|S)$")>; +def : InstRW<[GenericWriteFPUS], (instregex "^CMP_SEQ_(D|S)$")>; +def : InstRW<[GenericWriteFPUS], (instregex "^CMP_SLE_(D|S)$")>; +def : InstRW<[GenericWriteFPUS], (instregex "^CMP_SLT_(D|S)$")>; +def : InstRW<[GenericWriteFPUS], (instregex "^CMP_SUEQ_(D|S)$")>; +def : InstRW<[GenericWriteFPUS], (instregex "^CMP_SULE_(D|S)$")>; +def : InstRW<[GenericWriteFPUS], (instregex "^CMP_SULT_(D|S)$")>; +def : InstRW<[GenericWriteFPUS], (instregex "^CMP_SUN_(D|S)$")>; def : InstRW<[GenericWriteFPUS], (instregex "^FS(AF|EQ|LT|LE|NE|OR)_(W|D)$")>; def : InstRW<[GenericWriteFPUS], (instregex "^FSUEQ_(W|D)$")>; def : InstRW<[GenericWriteFPUS], (instregex "^FSULE_(W|D)$")>; @@ -995,7 +1524,6 @@ def : InstRW<[GenericWriteFPUS], (instregex "^FLOG2_(W|D)$")>; // interleave right/left, interleave even/odd, insert def : InstRW<[GenericWriteMSAShortLogic], (instregex "^(ILVR|ILVL)_[BHWD]$")>; def : InstRW<[GenericWriteMSAShortLogic], (instregex "^(ILVEV|ILVOD)_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortLogic], (instregex "^INSVE_[BHWD]$")>; // subs_?.[bhwd], subsus_?.[bhwd], subsuu_?.[bhwd], subvi.[bhwd], subv.[bhwd], def : InstRW<[GenericWriteMSAShortInt], (instregex "^SUBS_(S|U)_[BHWD]$")>; @@ -1027,6 +1555,8 @@ def : InstRW<[GenericWriteMSAShortLogic], (instregex "^(SLL|SLLI)_[BHWD]$")>; def : InstRW<[GenericWriteMSAShortLogic], (instregex "^(PCKEV|PCKOD)_[BHWD]$")>; def : InstRW<[GenericWriteMSAShortLogic], (instregex "^(NLOC|NLZC)_[BHWD]$")>; def : InstRW<[GenericWriteMSAShortLogic], (instregex "^INSVE_[BHWD]$")>; +def : InstRW<[GenericWriteMSAShortLogic], (instregex "^INSERT_F(D|W)_PSEUDO$")>; +def : InstRW<[GenericWriteMSAShortLogic], (instregex "^FILL_F(D|W)_PSEUDO$")>; // dpadd_?.[bhwd], dpsub_?.[bhwd], dotp_?.[bhwd], msubv.[bhwd], maddv.[bhwd] // mulv.[bhwd]. @@ -1062,5 +1592,23 @@ def : InstRW<[GenericWriteFPUMoveGPRFPU], (instregex "^COPY_U_[BHW]$")>; def : InstRW<[GenericWriteFPUMoveGPRFPU], (instregex "^COPY_S_[BHWD]$")>; def : InstRW<[GenericWriteFPUStore], (instregex "^ST_[BHWD]$")>; +def : InstRW<[GenericWriteFPUStore], (instrs ST_F16)>; def : InstRW<[GenericWriteFPULoad], (instregex "^LD_[BHWD]$")>; +def : InstRW<[GenericWriteFPULoad], (instrs LD_F16)>; + +// Atomic instructions + +// FIXME: Define `WriteAtomic` in the MipsSchedule.td and +// attach it to the Atomic2OpsPostRA, AtomicCmpSwapPostRA, ... +// classes. Then just define resources for the `WriteAtomic` in each +// machine models. +def GenericAtomic : ProcResource<1> { let BufferSize = 1; } +def GenericWriteAtomic : SchedWriteRes<[GenericAtomic]> { let Latency = 2; } + +def : InstRW<[GenericWriteAtomic], + (instregex "^ATOMIC_SWAP_I(8|16|32|64)_POSTRA$")>; +def : InstRW<[GenericWriteAtomic], + (instregex "^ATOMIC_CMP_SWAP_I(8|16|32|64)_POSTRA$")>; +def : InstRW<[GenericWriteAtomic], + (instregex "^ATOMIC_LOAD_(ADD|SUB|AND|OR|XOR|NAND)_I(8|16|32|64)_POSTRA$")>; } diff --git a/lib/Target/Mips/MipsScheduleP5600.td b/lib/Target/Mips/MipsScheduleP5600.td index 846fa11494c7..f97b03bff08e 100644 --- a/lib/Target/Mips/MipsScheduleP5600.td +++ b/lib/Target/Mips/MipsScheduleP5600.td @@ -1,9 +1,8 @@ //==- MipsScheduleP5600.td - P5600 Scheduling Definitions --*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -13,12 +12,13 @@ def MipsP5600Model : SchedMachineModel { int LoadLatency = 4; int MispredictPenalty = 8; // TODO: Estimated - let CompleteModel = 0; + let CompleteModel = 1; let FullInstRWOverlapCheck = 1; - list<Predicate> UnsupportedFeatures = [HasMips32r6, HasMips64r6, - HasMips3, HasMips64r2, HasCnMips, - InMicroMips, InMips16Mode, + list<Predicate> UnsupportedFeatures = [HasMips3, HasMips32r6, HasMips64, + HasMips64r2, HasMips64r5, HasMips64r6, + IsGP64bit, IsPTR64bit, + InMicroMips, InMips16Mode, HasCnMips, HasDSP, HasDSPR2, HasMT, HasCRC]; } @@ -59,15 +59,21 @@ def P5600WriteJumpAndLink : SchedWriteRes<[P5600IssueCTISTD, P5600CTISTD]> { let Latency = 2; } +def P5600Nop : SchedWriteRes<[P5600IssueCTISTD]> { + let Latency = 0; +} + +def : InstRW<[P5600Nop], (instrs SSNOP, NOP)>; + // b, beq, beql, bg[et]z, bl[et]z, bne, bnel, j, syscall, jal, bltzal, // jalr, jr.hb, jr def : InstRW<[P5600WriteJump], (instrs B, BAL, BAL_BR, BEQ, BEQL, BGEZ, BGEZAL, BGEZALL, BGEZL, BGTZ, BGTZL, BLEZ, BLEZL, BLTZ, BLTZAL, BLTZALL, BLTZL, BNE, BNEL, BREAK, - DERET, ERET, ERETNC, J, JR, JR_HB, + DERET, ERET, ERet, ERETNC, J, JR, JR_HB, PseudoIndirectBranch, PseudoIndirectHazardBranch, PseudoReturn, - SDBBP, SSNOP, SYSCALL, TAILCALL, TAILCALLREG, + SDBBP, SYSCALL, RetRA, TAILCALL, TAILCALLREG, TAILCALLREGHB, TEQ, TEQI, TGE, TGEI, TGEIU, TGEU, TLT, TLTI, TLTU, TNE, TNEI, TRAP, TTLTIU, WAIT, PAUSE)>; @@ -90,6 +96,11 @@ def : InstRW<[P5600COP2], (instrs MFC2, MTC2)> { let Unsupported = 1; } +// MIPS Virtualization ASE +// ======================= +def : InstRW<[P5600COP0], (instrs HYPCALL, MFGC0, MFHGC0, MTGC0, MTHGC0, + TLBGINV, TLBGINVF, TLBGP, TLBGR, TLBGWI, TLBGWR)>; + // LDST Pipeline // ------------- @@ -288,6 +299,8 @@ def : InstRW<[P5600WriteMSAShortInt], (instregex "^(BCLR|BCLRI)_[BHWD]$")>; def : InstRW<[P5600WriteMSAShortInt], (instregex "^(BNEG|BNEGI)_[BHWD]$")>; def : InstRW<[P5600WriteMSAShortInt], (instregex "^(BSEL_V|BSELI_B)$")>; def : InstRW<[P5600WriteMSAShortInt], (instregex "^BMN*Z.*$")>; +def : InstRW<[P5600WriteMSAShortInt], + (instregex "^BSEL_(H|W|D|FW|FD)_PSEUDO$")>; // pcnt.[bhwd], sat_s.[bhwd], sat_u.bhwd] def : InstRW<[P5600WriteMSAOther3], (instregex "^PCNT_[BHWD]$")>; @@ -335,6 +348,10 @@ def : InstRW<[P5600WriteMSAShortLogic], (instregex "^MOVE_V$")>; def : InstRW<[P5600WriteMSAShortLogic], (instregex "^LDI_[BHWD]$")>; def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(AND|OR|[XN]OR)_V$")>; def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(AND|OR|[XN]OR)I_B$")>; +def : InstRW<[P5600WriteMSAShortLogic], + (instregex "^(AND|OR|[XN]OR)_V_[DHW]_PSEUDO$")>; +def : InstRW<[P5600WriteMSAShortLogic], (instregex "^FILL_F(D|W)_PSEUDO$")>; +def : InstRW<[P5600WriteMSAShortLogic], (instregex "^INSERT_F(D|W)_PSEUDO$")>; // fexp2_w, fexp2_d def : InstRW<[P5600WriteFPUS], (instregex "^FEXP2_(W|D)$")>; @@ -427,17 +444,19 @@ def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(NLOC|NLZC)_[BHWD]$")>; // ---------- // // add.[ds], add.ps, cvt.d.[sw], cvt.s.[dw], cvt.w.[sd], cvt.[sw].ps, -// cvt.ps.[sw], c.<cc>.[ds], c.<cc>.ps, mul.[ds], mul.ps, sub.[ds], sub.ps, -// trunc.w.[ds], trunc.w.ps +// cvt.ps.[sw], cvt.s.(pl|pu), c.<cc>.[ds], c.<cc>.ps, mul.[ds], mul.ps, +// pl[lu].ps, sub.[ds], sub.ps, trunc.w.[ds], trunc.w.ps def : InstRW<[P5600WriteFPUL], (instrs FADD_D32, FADD_D64, FADD_S, FMUL_D32, FMUL_D64, FMUL_S, FSUB_D32, FSUB_D64, FSUB_S)>; def : InstRW<[P5600WriteFPUL], (instregex "^TRUNC_(L|W)_(S|D32|D64)$")>; def : InstRW<[P5600WriteFPUL], (instregex "^CVT_(S|D32|D64|L|W)_(S|D32|D64|L|W)$")>; +def : InstRW<[P5600WriteFPUL], (instrs CVT_PS_S64, CVT_S_PL64, CVT_S_PU64)>; def : InstRW<[P5600WriteFPUL], (instregex "^C_[A-Z]+_(S|D32|D64)$")>; def : InstRW<[P5600WriteFPUL], (instregex "^FCMP_(S32|D32|D64)$")>; def : InstRW<[P5600WriteFPUL], (instregex "^PseudoCVT_(S|D32|D64)_(L|W)$")>; +def : InstRW<[P5600WriteFPUL], (instrs PLL_PS64, PLU_PS64)>; // div.[ds], div.ps def : InstRW<[P5600WriteFPUDivS], (instrs FDIV_S)>; @@ -555,16 +574,20 @@ def : InstRW<[P5600WriteMoveFPUToGPR], (instrs BC1F, BC1FL, BC1T, BC1TL, CFC1, ExtractElementF64_64)>; // swc1, swxc1, st.[bhwd] -def : InstRW<[P5600WriteStoreFPUS], (instrs SDC1, SDXC1, SUXC1, SWC1, SWXC1)>; +def : InstRW<[P5600WriteStoreFPUS], (instrs SDC1, SDC164, SDXC1, SDXC164, + SWC1, SWXC1, SUXC1, SUXC164)>; def : InstRW<[P5600WriteStoreFPUS], (instregex "^ST_[BHWD]$")>; +def : InstRW<[P5600WriteStoreFPUS], (instrs ST_F16)>; // movn.[ds], movz.[ds] def : InstRW<[P5600WriteStoreFPUL], (instrs MOVN_I_D32, MOVN_I_D64, MOVN_I_S, MOVZ_I_D32, MOVZ_I_D64, MOVZ_I_S)>; // l[dw]x?c1, ld.[bhwd] -def : InstRW<[P5600WriteLoadFPU], (instrs LDC1, LDXC1, LWC1, LWXC1, LUXC1)>; +def : InstRW<[P5600WriteLoadFPU], (instrs LDC1, LDC164, LDXC1, LDXC164, + LWC1, LWXC1, LUXC1, LUXC164)>; def : InstRW<[P5600WriteLoadFPU], (instregex "LD_[BHWD]")>; +def : InstRW<[P5600WriteLoadFPU], (instrs LD_F16)>; // Unsupported Instructions // ======================== @@ -593,4 +616,20 @@ def : InstRW<[P5600WriteFPUL], (instregex "^ROUND_(L|W)_(S|D32|D64)$")>; // Reason behind guess: rotr is in the same category and the two register forms // generally follow the immediate forms in this category def : InstRW<[P5600WriteEitherALU], (instrs ROTRV)>; + +// Atomic instructions + +// FIXME: Define `WriteAtomic` in the MipsSchedule.td and +// attach it to the Atomic2OpsPostRA, AtomicCmpSwapPostRA, ... +// classes. Then just define resources for the `WriteAtomic` in each +// machine models. +def P5600Atomic : ProcResource<1> { let BufferSize = 1; } +def P5600WriteAtomic : SchedWriteRes<[P5600Atomic]> { let Latency = 2; } + +def : InstRW<[P5600WriteAtomic], + (instregex "^ATOMIC_SWAP_I(8|16|32|64)_POSTRA$")>; +def : InstRW<[P5600WriteAtomic], + (instregex "^ATOMIC_CMP_SWAP_I(8|16|32|64)_POSTRA$")>; +def : InstRW<[P5600WriteAtomic], + (instregex "^ATOMIC_LOAD_(ADD|SUB|AND|OR|XOR|NAND)_I(8|16|32|64)_POSTRA$")>; } diff --git a/lib/Target/Mips/MipsSubtarget.cpp b/lib/Target/Mips/MipsSubtarget.cpp index 0c39a45467c4..d021b3d021b1 100644 --- a/lib/Target/Mips/MipsSubtarget.cpp +++ b/lib/Target/Mips/MipsSubtarget.cpp @@ -1,9 +1,8 @@ //===-- MipsSubtarget.cpp - Mips Subtarget Information --------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -73,7 +72,7 @@ MipsSubtarget::MipsSubtarget(const Triple &TT, StringRef CPU, StringRef FS, unsigned StackAlignOverride) : MipsGenSubtargetInfo(TT, CPU, FS), MipsArchVersion(MipsDefault), IsLittle(little), IsSoftFloat(false), IsSingleFloat(false), IsFPXX(false), - NoABICalls(false), IsFP64bit(false), UseOddSPReg(true), + NoABICalls(false), Abs2008(false), IsFP64bit(false), UseOddSPReg(true), IsNaN2008bit(false), IsGP64bit(false), HasVFPU(false), HasCnMips(false), HasMips3_32(false), HasMips3_32r2(false), HasMips4_32(false), HasMips4_32r2(false), HasMips5_32r2(false), InMips16Mode(false), @@ -109,6 +108,11 @@ MipsSubtarget::MipsSubtarget(const Triple &TT, StringRef CPU, StringRef FS, "See -mattr=+fp64.", false); + if (isFP64bit() && !hasMips64() && hasMips32() && !hasMips32r2()) + report_fatal_error( + "FPU with 64-bit registers is not available on MIPS32 pre revision 2. " + "Use -mcpu=mips32r2 or greater."); + if (!isABI_O32() && !useOddSPReg()) report_fatal_error("-mattr=+nooddspreg requires the O32 ABI.", false); @@ -129,11 +133,18 @@ MipsSubtarget::MipsSubtarget(const Triple &TT, StringRef CPU, StringRef FS, report_fatal_error( "indirect jumps with hazard barriers requires MIPS32R2 or later"); } + if (inAbs2008Mode() && hasMips32() && !hasMips32r2()) { + report_fatal_error("IEEE 754-2008 abs.fmt is not supported for the given " + "architecture.", + false); + } + if (hasMips32r6()) { StringRef ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6"; assert(isFP64bit()); assert(isNaN2008()); + assert(inAbs2008Mode()); if (hasDSP()) report_fatal_error(ISA + " is not compatible with the DSP ASE", false); } diff --git a/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h index ad8f4848b870..aa1200579fc8 100644 --- a/lib/Target/Mips/MipsSubtarget.h +++ b/lib/Target/Mips/MipsSubtarget.h @@ -1,9 +1,8 @@ //===-- MipsSubtarget.h - Define Subtarget for the Mips ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -87,6 +86,9 @@ class MipsSubtarget : public MipsGenSubtargetInfo { // NoABICalls - Disable SVR4-style position-independent code. bool NoABICalls; + // Abs2008 - Use IEEE 754-2008 abs.fmt instruction. + bool Abs2008; + // IsFP64bit - The target processor has 64-bit floating point registers. bool IsFP64bit; @@ -273,6 +275,7 @@ public: bool useOddSPReg() const { return UseOddSPReg; } bool noOddSPReg() const { return !UseOddSPReg; } bool isNaN2008() const { return IsNaN2008bit; } + bool inAbs2008Mode() const { return Abs2008; } bool isGP64bit() const { return IsGP64bit; } bool isGP32bit() const { return !IsGP64bit; } unsigned getGPRSizeInBytes() const { return isGP64bit() ? 8 : 4; } diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp index 8466298cf36f..c878abb042e4 100644 --- a/lib/Target/Mips/MipsTargetMachine.cpp +++ b/lib/Target/Mips/MipsTargetMachine.cpp @@ -1,9 +1,8 @@ //===-- MipsTargetMachine.cpp - Define TargetMachine for Mips -------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -19,6 +18,7 @@ #include "MipsSEISelDAGToDAG.h" #include "MipsSubtarget.h" #include "MipsTargetObjectFile.h" +#include "TargetInfo/MipsTargetInfo.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" @@ -205,8 +205,7 @@ MipsTargetMachine::getSubtargetImpl(const Function &F) const { void MipsTargetMachine::resetSubtarget(MachineFunction *MF) { LLVM_DEBUG(dbgs() << "resetSubtarget\n"); - Subtarget = const_cast<MipsSubtarget *>(getSubtargetImpl(MF->getFunction())); - MF->setSubtarget(Subtarget); + Subtarget = &MF->getSubtarget<MipsSubtarget>(); } namespace { @@ -240,6 +239,8 @@ public: bool addLegalizeMachineIR() override; bool addRegBankSelect() override; bool addGlobalInstructionSelect() override; + + std::unique_ptr<CSEConfigBase> getCSEConfig() const override; }; } // end anonymous namespace @@ -248,6 +249,10 @@ TargetPassConfig *MipsTargetMachine::createPassConfig(PassManagerBase &PM) { return new MipsPassConfig(*this, PM); } +std::unique_ptr<CSEConfigBase> MipsPassConfig::getCSEConfig() const { + return getStandardCSEConfigForOpt(TM->getOptLevel()); +} + void MipsPassConfig::addIRPasses() { TargetPassConfig::addIRPasses(); addPass(createAtomicExpandPass()); diff --git a/lib/Target/Mips/MipsTargetMachine.h b/lib/Target/Mips/MipsTargetMachine.h index d9b73d151119..25300504a02d 100644 --- a/lib/Target/Mips/MipsTargetMachine.h +++ b/lib/Target/Mips/MipsTargetMachine.h @@ -1,9 +1,8 @@ //===- MipsTargetMachine.h - Define TargetMachine for Mips ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -30,7 +29,7 @@ class MipsTargetMachine : public LLVMTargetMachine { std::unique_ptr<TargetLoweringObjectFile> TLOF; // Selected ABI MipsABIInfo ABI; - MipsSubtarget *Subtarget; + const MipsSubtarget *Subtarget; MipsSubtarget DefaultSubtarget; MipsSubtarget NoMips16Subtarget; MipsSubtarget Mips16Subtarget; @@ -66,10 +65,6 @@ public: bool isLittleEndian() const { return isLittle; } const MipsABIInfo &getABI() const { return ABI; } - - bool isMachineVerifierClean() const override { - return false; - } }; /// Mips32/64 big endian target machine. diff --git a/lib/Target/Mips/MipsTargetObjectFile.cpp b/lib/Target/Mips/MipsTargetObjectFile.cpp index f53ee0631b5e..0852b5a18c68 100644 --- a/lib/Target/Mips/MipsTargetObjectFile.cpp +++ b/lib/Target/Mips/MipsTargetObjectFile.cpp @@ -1,9 +1,8 @@ //===-- MipsTargetObjectFile.cpp - Mips Object Files ----------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MipsTargetObjectFile.h b/lib/Target/Mips/MipsTargetObjectFile.h index a37ec154ff79..bdf485f83260 100644 --- a/lib/Target/Mips/MipsTargetObjectFile.h +++ b/lib/Target/Mips/MipsTargetObjectFile.h @@ -1,9 +1,8 @@ //===-- llvm/Target/MipsTargetObjectFile.h - Mips Object Info ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MipsTargetStreamer.h b/lib/Target/Mips/MipsTargetStreamer.h index a282366f6d40..1fa8ebadd643 100644 --- a/lib/Target/Mips/MipsTargetStreamer.h +++ b/lib/Target/Mips/MipsTargetStreamer.h @@ -1,9 +1,8 @@ //===-- MipsTargetStreamer.h - Mips Target Streamer ------------*- C++ -*--===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -92,6 +91,7 @@ public: // PIC support virtual void emitDirectiveCpLoad(unsigned RegNo); + virtual void emitDirectiveCpLocal(unsigned RegNo); virtual bool emitDirectiveCpRestore(int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc, const MCSubtargetInfo *STI); @@ -200,6 +200,7 @@ protected: bool FrameInfoSet; int FrameOffset; unsigned FrameReg; + unsigned GPReg; unsigned ReturnReg; private: @@ -275,6 +276,7 @@ public: // PIC support void emitDirectiveCpLoad(unsigned RegNo) override; + void emitDirectiveCpLocal(unsigned RegNo) override; /// Emit a .cprestore directive. If the offset is out of range then it will /// be synthesized using the assembler temporary. @@ -346,6 +348,7 @@ public: // PIC support void emitDirectiveCpLoad(unsigned RegNo) override; + void emitDirectiveCpLocal(unsigned RegNo) override; bool emitDirectiveCpRestore(int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc, const MCSubtargetInfo *STI) override; void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, diff --git a/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp b/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp index 22be564b6502..0082ca34cdbd 100644 --- a/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp +++ b/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp @@ -1,14 +1,12 @@ //===-- MipsTargetInfo.cpp - Mips Target Implementation -------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// -#include "Mips.h" -#include "llvm/IR/Module.h" +#include "TargetInfo/MipsTargetInfo.h" #include "llvm/Support/TargetRegistry.h" using namespace llvm; diff --git a/lib/Target/Mips/TargetInfo/MipsTargetInfo.h b/lib/Target/Mips/TargetInfo/MipsTargetInfo.h new file mode 100644 index 000000000000..d91a2719108d --- /dev/null +++ b/lib/Target/Mips/TargetInfo/MipsTargetInfo.h @@ -0,0 +1,23 @@ +//===-- MipsTargetInfo.h - Mips Target Implementation -----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_MIPS_TARGETINFO_MIPSTARGETINFO_H +#define LLVM_LIB_TARGET_MIPS_TARGETINFO_MIPSTARGETINFO_H + +namespace llvm { + +class Target; + +Target &getTheMipsTarget(); +Target &getTheMipselTarget(); +Target &getTheMips64Target(); +Target &getTheMips64elTarget(); + +} // namespace llvm + +#endif // LLVM_LIB_TARGET_MIPS_TARGETINFO_MIPSTARGETINFO_H |
