summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/Target/Mips
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/Target/Mips')
-rw-r--r--contrib/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp1322
-rw-r--r--contrib/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp87
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp12
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h41
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp82
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h10
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp70
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp10
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h15
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h3
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp6
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp61
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h27
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp10
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h6
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp16
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp8
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp59
-rw-r--r--contrib/llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td40
-rw-r--r--contrib/llvm/lib/Target/Mips/MicroMipsInstrInfo.td33
-rw-r--r--contrib/llvm/lib/Target/Mips/MicroMipsSizeReduction.cpp392
-rw-r--r--contrib/llvm/lib/Target/Mips/Mips.h13
-rw-r--r--contrib/llvm/lib/Target/Mips/Mips.td10
-rw-r--r--contrib/llvm/lib/Target/Mips/Mips16FrameLowering.cpp22
-rw-r--r--contrib/llvm/lib/Target/Mips/Mips16HardFloat.cpp36
-rw-r--r--contrib/llvm/lib/Target/Mips/Mips16InstrInfo.td2
-rw-r--r--contrib/llvm/lib/Target/Mips/Mips32r6InstrInfo.td12
-rw-r--r--contrib/llvm/lib/Target/Mips/Mips64InstrInfo.td276
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp150
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsAsmPrinter.h16
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsCCState.cpp76
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsCCState.h47
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsCallingConv.td10
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsConstantIslandPass.cpp119
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsDSPInstrInfo.td5
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp68
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsFastISel.cpp144
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsFrameLowering.cpp2
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsHazardSchedule.cpp27
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp511
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsISelLowering.h81
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsInstrFPU.td50
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsInstrInfo.cpp41
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsInstrInfo.h3
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsInstrInfo.td266
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsLongBranch.cpp54
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsMSAInstrInfo.td74
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsMTInstrFormats.td78
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsMTInstrInfo.td98
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsMachineFunction.cpp32
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsMachineFunction.h34
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp18
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsOptimizePICCall.cpp15
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsOptionRecord.h17
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsOs16.cpp8
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsRegisterInfo.cpp4
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsRegisterInfo.td66
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp63
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsSEFrameLowering.h9
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp342
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.h3
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsSEISelLowering.cpp264
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp41
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsSchedule.td14
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsScheduleGeneric.td14
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsScheduleP5600.td2
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsSubtarget.cpp17
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsSubtarget.h32
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsTargetMachine.cpp69
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsTargetMachine.h23
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.cpp2
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsTargetStreamer.h6
-rw-r--r--contrib/llvm/lib/Target/Mips/Relocation.txt125
73 files changed, 4452 insertions, 1369 deletions
diff --git a/contrib/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/contrib/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index d054578..e12188e 100644
--- a/contrib/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/contrib/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -7,47 +7,68 @@
//
//===----------------------------------------------------------------------===//
+#include "MCTargetDesc/MipsABIFlagsSection.h"
#include "MCTargetDesc/MipsABIInfo.h"
+#include "MCTargetDesc/MipsBaseInfo.h"
#include "MCTargetDesc/MipsMCExpr.h"
#include "MCTargetDesc/MipsMCTargetDesc.h"
-#include "MipsRegisterInfo.h"
-#include "MipsTargetObjectFile.h"
#include "MipsTargetStreamer.h"
-#include "MCTargetDesc/MipsBaseInfo.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCInstBuilder.h"
+#include "llvm/MC/MCInstrDesc.h"
+#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCParser/MCAsmParser.h"
+#include "llvm/MC/MCParser/MCAsmParserExtension.h"
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCSymbolELF.h"
+#include "llvm/MC/MCValue.h"
+#include "llvm/MC/SubtargetFeature.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
-#include "llvm/Support/ELF.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/SMLoc.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
#include <memory>
+#include <string>
+#include <utility>
using namespace llvm;
#define DEBUG_TYPE "mips-asm-parser"
namespace llvm {
+
class MCInstrInfo;
-}
+
+} // end namespace llvm
namespace {
+
class MipsAssemblerOptions {
public:
- MipsAssemblerOptions(const FeatureBitset &Features_) :
- ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
+ MipsAssemblerOptions(const FeatureBitset &Features_) : Features(Features_) {}
MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
ATReg = Opts->getATRegIndex();
@@ -84,12 +105,13 @@ public:
static const FeatureBitset AllArchRelatedMask;
private:
- unsigned ATReg;
- bool Reorder;
- bool Macro;
+ unsigned ATReg = 1;
+ bool Reorder = true;
+ bool Macro = true;
FeatureBitset Features;
};
-}
+
+} // end anonymous namespace
const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
@@ -103,6 +125,7 @@ const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
};
namespace {
+
class MipsAsmParser : public MCTargetAsmParser {
MipsTargetStreamer &getTargetStreamer() {
MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
@@ -147,6 +170,8 @@ class MipsAsmParser : public MCTargetAsmParser {
bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
+ bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);
+
bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
SMLoc NameLoc, OperandVector &Operands) override;
@@ -192,9 +217,15 @@ class MipsAsmParser : public MCTargetAsmParser {
unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
MCStreamer &Out, const MCSubtargetInfo *STI);
+ bool emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, MCSymbol *Sym);
+
bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
MCStreamer &Out, const MCSubtargetInfo *STI);
+ bool expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR, bool Is64FPU,
+ SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
+
bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
const MCOperand &Offset, bool Is32BitAddress,
SMLoc IDLoc, MCStreamer &Out,
@@ -252,6 +283,18 @@ class MipsAsmParser : public MCTargetAsmParser {
bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
const MCSubtargetInfo *STI);
+ bool expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
+
+ bool expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
+
+ bool expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
+
+ bool expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
+
bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
const MCSubtargetInfo *STI, bool IsLoad);
@@ -279,6 +322,7 @@ class MipsAsmParser : public MCTargetAsmParser {
bool parseDirectiveSet();
bool parseDirectiveOption();
bool parseInsnDirective();
+ bool parseRSectionDirective(StringRef Section);
bool parseSSectionDirective(StringRef Section, unsigned Type);
bool parseSetAtDirective();
@@ -299,6 +343,8 @@ class MipsAsmParser : public MCTargetAsmParser {
bool parseSetPushDirective();
bool parseSetSoftFloatDirective();
bool parseSetHardFloatDirective();
+ bool parseSetMtDirective();
+ bool parseSetNoMtDirective();
bool parseSetAssignment();
@@ -339,6 +385,8 @@ class MipsAsmParser : public MCTargetAsmParser {
/// This should be used in pseudo-instruction expansions which need AT.
unsigned getATReg(SMLoc Loc);
+ bool canUseATReg();
+
bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
const MCSubtargetInfo *STI);
@@ -466,9 +514,11 @@ public:
bool isGP64bit() const {
return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
}
+
bool isFP64bit() const {
return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
}
+
const MipsABIInfo &getABI() const { return ABI; }
bool isABI_N32() const { return ABI.IsN32(); }
bool isABI_N64() const { return ABI.IsN64(); }
@@ -484,48 +534,63 @@ public:
bool inMicroMipsMode() const {
return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
}
+
bool hasMips1() const {
return getSTI().getFeatureBits()[Mips::FeatureMips1];
}
+
bool hasMips2() const {
return getSTI().getFeatureBits()[Mips::FeatureMips2];
}
+
bool hasMips3() const {
return getSTI().getFeatureBits()[Mips::FeatureMips3];
}
+
bool hasMips4() const {
return getSTI().getFeatureBits()[Mips::FeatureMips4];
}
+
bool hasMips5() const {
return getSTI().getFeatureBits()[Mips::FeatureMips5];
}
+
bool hasMips32() const {
return getSTI().getFeatureBits()[Mips::FeatureMips32];
}
+
bool hasMips64() const {
return getSTI().getFeatureBits()[Mips::FeatureMips64];
}
+
bool hasMips32r2() const {
return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
}
+
bool hasMips64r2() const {
return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
}
+
bool hasMips32r3() const {
return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
}
+
bool hasMips64r3() const {
return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
}
+
bool hasMips32r5() const {
return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
}
+
bool hasMips64r5() const {
return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
}
+
bool hasMips32r6() const {
return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
}
+
bool hasMips64r6() const {
return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
}
@@ -533,15 +598,19 @@ public:
bool hasDSP() const {
return getSTI().getFeatureBits()[Mips::FeatureDSP];
}
+
bool hasDSPR2() const {
return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
}
+
bool hasDSPR3() const {
return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
}
+
bool hasMSA() const {
return getSTI().getFeatureBits()[Mips::FeatureMSA];
}
+
bool hasCnMips() const {
return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
}
@@ -561,6 +630,9 @@ public:
bool useSoftFloat() const {
return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
}
+ bool hasMT() const {
+ return getSTI().getFeatureBits()[Mips::FeatureMT];
+ }
/// Warn if RegIndex is the same as the current AT.
void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
@@ -627,9 +699,6 @@ public:
}
}
};
-}
-
-namespace {
/// MipsOperand - Instances of this class represent a parsed Mips machine
/// instruction.
@@ -671,6 +740,22 @@ public:
MipsOperand(KindTy K, MipsAsmParser &Parser)
: MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
+ ~MipsOperand() override {
+ switch (Kind) {
+ case k_Immediate:
+ break;
+ case k_Memory:
+ delete Mem.Base;
+ break;
+ case k_RegList:
+ delete RegList.List;
+ case k_RegisterIndex:
+ case k_Token:
+ case k_RegPair:
+ break;
+ }
+ }
+
private:
/// For diagnostics, and checking the assembler temporary
MipsAsmParser &AsmParser;
@@ -716,7 +801,7 @@ private:
const MCRegisterInfo *RegInfo,
SMLoc S, SMLoc E,
MipsAsmParser &Parser) {
- auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
+ auto Op = llvm::make_unique<MipsOperand>(k_RegisterIndex, Parser);
Op->RegIdx.Index = Index;
Op->RegIdx.RegInfo = RegInfo;
Op->RegIdx.Kind = RegKind;
@@ -896,6 +981,16 @@ public:
/// Render the operand to an MCInst as a GPR32
/// Asserts if the wrong number of operands are requested, or the operand
/// is not a k_RegisterIndex compatible with RegKind_GPR
+ void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
+ }
+
+ void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
+ }
+
void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
@@ -929,6 +1024,16 @@ public:
Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
}
+ void addStrictlyAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
+ }
+
+ void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
+ }
+
void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
@@ -945,6 +1050,15 @@ public:
"registers");
}
+ void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
+ // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
+ if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
+ AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
+ "registers");
+ }
+
void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
@@ -1104,45 +1218,58 @@ public:
// $0/$zero here so that MCK_ZERO works correctly.
return isGPRAsmReg() && RegIdx.Index == 0;
}
+
bool isRegIdx() const { return Kind == k_RegisterIndex; }
bool isImm() const override { return Kind == k_Immediate; }
+
bool isConstantImm() const {
int64_t Res;
return isImm() && getImm()->evaluateAsAbsolute(Res);
}
+
bool isConstantImmz() const {
return isConstantImm() && getConstantImm() == 0;
}
+
template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
}
+
template <unsigned Bits> bool isSImm() const {
return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
}
+
template <unsigned Bits> bool isUImm() const {
return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
}
+
template <unsigned Bits> bool isAnyImm() const {
return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
isUInt<Bits>(getConstantImm()))
: isImm();
}
+
template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
}
+
template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
return isConstantImm() && getConstantImm() >= Bottom &&
getConstantImm() <= Top;
}
+
bool isToken() const override {
// Note: It's not possible to pretend that other operand kinds are tokens.
// The matcher emitter checks tokens first.
return Kind == k_Token;
}
+
bool isMem() const override { return Kind == k_Memory; }
+
bool isConstantMemOff() const {
return isMem() && isa<MCConstantExpr>(getMemOff());
}
+
// Allow relocation operators.
// FIXME: This predicate and others need to look through binary expressions
// and determine whether a Value is a constant or not.
@@ -1160,28 +1287,34 @@ public:
bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
}
+
bool isMemWithGRPMM16Base() const {
return isMem() && getMemBase()->isMM16AsmReg();
}
+
template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
&& getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
}
+
template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
&& (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
&& (getMemBase()->getGPR32Reg() == Mips::SP);
}
+
template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
&& (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
&& (getMemBase()->getGPR32Reg() == Mips::GP);
}
+
template <unsigned Bits, unsigned ShiftLeftAmount>
bool isScaledUImm() const {
return isConstantImm() &&
isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
}
+
template <unsigned Bits, unsigned ShiftLeftAmount>
bool isScaledSImm() const {
if (isConstantImm() && isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
@@ -1193,6 +1326,7 @@ public:
bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
}
+
bool isRegList16() const {
if (!isRegList())
return false;
@@ -1217,14 +1351,18 @@ public:
return true;
}
+
bool isInvNum() const { return Kind == k_Immediate; }
+
bool isLSAImm() const {
if (!isConstantImm())
return false;
int64_t Val = getConstantImm();
return 1 <= Val && Val <= 4;
}
+
bool isRegList() const { return Kind == k_RegList; }
+
bool isMovePRegPair() const {
if (Kind != k_RegList || RegList.List->size() != 2)
return false;
@@ -1257,6 +1395,7 @@ public:
assert(Kind == k_Token && "Invalid access!");
return StringRef(Tok.Data, Tok.Length);
}
+
bool isRegPair() const {
return Kind == k_RegPair && RegIdx.Index <= 30;
}
@@ -1310,7 +1449,7 @@ public:
static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
MipsAsmParser &Parser) {
- auto Op = make_unique<MipsOperand>(k_Token, Parser);
+ auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser);
Op->Tok.Data = Str.data();
Op->Tok.Length = Str.size();
Op->StartLoc = S;
@@ -1385,7 +1524,7 @@ public:
static std::unique_ptr<MipsOperand>
CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
- auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
+ auto Op = llvm::make_unique<MipsOperand>(k_Immediate, Parser);
Op->Imm.Val = Val;
Op->StartLoc = S;
Op->EndLoc = E;
@@ -1395,7 +1534,7 @@ public:
static std::unique_ptr<MipsOperand>
CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
SMLoc E, MipsAsmParser &Parser) {
- auto Op = make_unique<MipsOperand>(k_Memory, Parser);
+ auto Op = llvm::make_unique<MipsOperand>(k_Memory, Parser);
Op->Mem.Base = Base.release();
Op->Mem.Off = Off;
Op->StartLoc = S;
@@ -1406,9 +1545,9 @@ public:
static std::unique_ptr<MipsOperand>
CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
MipsAsmParser &Parser) {
- assert (Regs.size() > 0 && "Empty list not allowed");
+ assert(Regs.size() > 0 && "Empty list not allowed");
- auto Op = make_unique<MipsOperand>(k_RegList, Parser);
+ auto Op = llvm::make_unique<MipsOperand>(k_RegList, Parser);
Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Op->StartLoc = StartLoc;
Op->EndLoc = EndLoc;
@@ -1418,7 +1557,7 @@ public:
static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
SMLoc S, SMLoc E,
MipsAsmParser &Parser) {
- auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
+ auto Op = llvm::make_unique<MipsOperand>(k_RegPair, Parser);
Op->RegIdx.Index = MOP.RegIdx.Index;
Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
Op->RegIdx.Kind = MOP.RegIdx.Kind;
@@ -1427,14 +1566,25 @@ public:
return Op;
}
+ bool isGPRZeroAsmReg() const {
+ return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0;
+ }
+
+ bool isGPRNonZeroAsmReg() const {
+ return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 &&
+ RegIdx.Index <= 31;
+ }
+
bool isGPRAsmReg() const {
return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
}
+
bool isMM16AsmReg() const {
if (!(isRegIdx() && RegIdx.Kind))
return false;
return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
|| RegIdx.Index == 16 || RegIdx.Index == 17);
+
}
bool isMM16AsmRegZero() const {
if (!(isRegIdx() && RegIdx.Kind))
@@ -1443,42 +1593,58 @@ public:
(RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
RegIdx.Index == 17);
}
+
bool isMM16AsmRegMoveP() const {
if (!(isRegIdx() && RegIdx.Kind))
return false;
return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
(RegIdx.Index >= 16 && RegIdx.Index <= 20));
}
+
bool isFGRAsmReg() const {
// AFGR64 is $0-$15 but we handle this in getAFGR64()
return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
}
+
+ bool isStrictlyFGRAsmReg() const {
+ // AFGR64 is $0-$15 but we handle this in getAFGR64()
+ return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31;
+ }
+
bool isHWRegsAsmReg() const {
return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
}
+
bool isCCRAsmReg() const {
return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
}
+
bool isFCCAsmReg() const {
if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
return false;
return RegIdx.Index <= 7;
}
+
bool isACCAsmReg() const {
return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
}
+
bool isCOP0AsmReg() const {
return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
}
+
bool isCOP2AsmReg() const {
return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
}
+
bool isCOP3AsmReg() const {
return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
}
+
bool isMSA128AsmReg() const {
return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
}
+
bool isMSACtrlAsmReg() const {
return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
}
@@ -1488,22 +1654,6 @@ public:
/// getEndLoc - Get the location of the last token of this operand.
SMLoc getEndLoc() const override { return EndLoc; }
- virtual ~MipsOperand() {
- switch (Kind) {
- case k_Immediate:
- break;
- case k_Memory:
- delete Mem.Base;
- break;
- case k_RegList:
- delete RegList.List;
- case k_RegisterIndex:
- case k_Token:
- case k_RegPair:
- break;
- }
- }
-
void print(raw_ostream &OS) const override {
switch (Kind) {
case k_Immediate:
@@ -1553,11 +1703,15 @@ public:
}
}
}; // class MipsOperand
-} // namespace
+
+} // end anonymous namespace
namespace llvm {
+
extern const MCInstrDesc MipsInsts[];
-}
+
+} // end namespace llvm
+
static const MCInstrDesc &getInstDesc(unsigned Opcode) {
return MipsInsts[Opcode];
}
@@ -1785,6 +1939,62 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
}
}
+ // Warn on division by zero. We're checking here as all instructions get
+ // processed here, not just the macros that need expansion.
+ //
+ // The MIPS backend models most of the divison instructions and macros as
+ // three operand instructions. The pre-R6 divide instructions however have
+ // two operands and explicitly define HI/LO as part of the instruction,
+ // not in the operands.
+ unsigned FirstOp = 1;
+ unsigned SecondOp = 2;
+ switch (Inst.getOpcode()) {
+ default:
+ break;
+ case Mips::SDivIMacro:
+ case Mips::UDivIMacro:
+ case Mips::DSDivIMacro:
+ case Mips::DUDivIMacro:
+ if (Inst.getOperand(2).getImm() == 0) {
+ if (Inst.getOperand(1).getReg() == Mips::ZERO ||
+ Inst.getOperand(1).getReg() == Mips::ZERO_64)
+ Warning(IDLoc, "dividing zero by zero");
+ else
+ Warning(IDLoc, "division by zero");
+ }
+ break;
+ case Mips::DSDIV:
+ case Mips::SDIV:
+ case Mips::UDIV:
+ case Mips::DUDIV:
+ case Mips::UDIV_MM:
+ case Mips::SDIV_MM:
+ FirstOp = 0;
+ SecondOp = 1;
+ LLVM_FALLTHROUGH;
+ case Mips::SDivMacro:
+ case Mips::DSDivMacro:
+ case Mips::UDivMacro:
+ case Mips::DUDivMacro:
+ case Mips::DIV:
+ case Mips::DIVU:
+ case Mips::DDIV:
+ case Mips::DDIVU:
+ case Mips::DIVU_MMR6:
+ case Mips::DDIVU_MM64R6:
+ case Mips::DIV_MMR6:
+ case Mips::DDIV_MM64R6:
+ if (Inst.getOperand(SecondOp).getReg() == Mips::ZERO ||
+ Inst.getOperand(SecondOp).getReg() == Mips::ZERO_64) {
+ if (Inst.getOperand(FirstOp).getReg() == Mips::ZERO ||
+ Inst.getOperand(FirstOp).getReg() == Mips::ZERO_64)
+ Warning(IDLoc, "dividing zero by zero");
+ else
+ Warning(IDLoc, "division by zero");
+ }
+ break;
+ }
+
// For PIC code convert unconditional jump to unconditional branch.
if ((Inst.getOpcode() == Mips::J || Inst.getOpcode() == Mips::J_MM) &&
inPicMode()) {
@@ -2135,6 +2345,8 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::BneImm:
case Mips::BeqImm:
+ case Mips::BEQLImmMacro:
+ case Mips::BNELImmMacro:
return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::BLT:
case Mips::BLE:
@@ -2170,15 +2382,19 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
case Mips::BGTULImmMacro:
return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::SDivMacro:
+ case Mips::SDivIMacro:
return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
: MER_Success;
case Mips::DSDivMacro:
+ case Mips::DSDivIMacro:
return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
: MER_Success;
case Mips::UDivMacro:
+ case Mips::UDivIMacro:
return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
: MER_Success;
case Mips::DUDivMacro:
+ case Mips::DUDivIMacro:
return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
: MER_Success;
case Mips::PseudoTRUNC_W_S:
@@ -2190,6 +2406,27 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
case Mips::PseudoTRUNC_W_D:
return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
: MER_Success;
+
+ case Mips::LoadImmSingleGPR:
+ return expandLoadImmReal(Inst, true, true, false, IDLoc, Out, STI)
+ ? MER_Fail
+ : MER_Success;
+ case Mips::LoadImmSingleFGR:
+ return expandLoadImmReal(Inst, true, false, false, IDLoc, Out, STI)
+ ? MER_Fail
+ : MER_Success;
+ case Mips::LoadImmDoubleGPR:
+ return expandLoadImmReal(Inst, false, true, false, IDLoc, Out, STI)
+ ? MER_Fail
+ : MER_Success;
+ case Mips::LoadImmDoubleFGR:
+ return expandLoadImmReal(Inst, false, false, true, IDLoc, Out, STI)
+ ? MER_Fail
+ : MER_Success;
+ case Mips::LoadImmDoubleFGR_32:
+ return expandLoadImmReal(Inst, false, false, false, IDLoc, Out, STI)
+ ? MER_Fail
+ : MER_Success;
case Mips::Ulh:
return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::Ulhu:
@@ -2200,11 +2437,24 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
case Mips::Usw:
return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::NORImm:
+ case Mips::NORImm64:
+ return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
+ case Mips::SLTImm64:
+ if (isInt<16>(Inst.getOperand(2).getImm())) {
+ Inst.setOpcode(Mips::SLTi64);
+ return MER_NotAMacro;
+ }
+ return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
+ case Mips::SLTUImm64:
+ if (isInt<16>(Inst.getOperand(2).getImm())) {
+ Inst.setOpcode(Mips::SLTiu64);
+ return MER_NotAMacro;
+ }
return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
- case Mips::ADDi:
- case Mips::ADDiu:
- case Mips::SLTi:
- case Mips::SLTiu:
+ case Mips::ADDi: case Mips::ADDi_MM:
+ case Mips::ADDiu: case Mips::ADDiu_MM:
+ case Mips::SLTi: case Mips::SLTi_MM:
+ case Mips::SLTiu: case Mips::SLTiu_MM:
if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
int64_t ImmValue = Inst.getOperand(2).getImm();
@@ -2214,9 +2464,9 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
: MER_Success;
}
return MER_NotAMacro;
- case Mips::ANDi:
- case Mips::ORi:
- case Mips::XORi:
+ case Mips::ANDi: case Mips::ANDi_MM: case Mips::ANDi64:
+ case Mips::ORi: case Mips::ORi_MM: case Mips::ORi64:
+ case Mips::XORi: case Mips::XORi_MM: case Mips::XORi64:
if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
int64_t ImmValue = Inst.getOperand(2).getImm();
@@ -2240,6 +2490,17 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::ABSMacro:
return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
+ case Mips::MULImmMacro:
+ case Mips::DMULImmMacro:
+ return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
+ case Mips::MULOMacro:
+ case Mips::DMULOMacro:
+ return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
+ case Mips::MULOUMacro:
+ case Mips::DMULOUMacro:
+ return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
+ case Mips::DMULMacro:
+ return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::LDMacro:
case Mips::SDMacro:
return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
@@ -2392,7 +2653,6 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
uint16_t Bits15To0 = ImmValue & 0xffff;
-
if (!Is32BitImm && !isInt<32>(ImmValue)) {
// Traditional behaviour seems to special case this particular value. It's
// not clear why other masks are handled differently.
@@ -2535,6 +2795,7 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
bool Is32BitSym, SMLoc IDLoc,
MCStreamer &Out,
const MCSubtargetInfo *STI) {
+ // FIXME: These expansions do not respect -mxgot.
MipsTargetStreamer &TOut = getTargetStreamer();
bool UseSrcReg = SrcReg != Mips::NoRegister;
warnIfNoMacro(IDLoc);
@@ -2554,8 +2815,12 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
// symbol in the final relocation is external and not modified with a
// constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
- Res.getConstant() == 0 && !Res.getSymA()->getSymbol().isInSection() &&
- !Res.getSymA()->getSymbol().isTemporary()) {
+ Res.getConstant() == 0 &&
+ !(Res.getSymA()->getSymbol().isInSection() ||
+ Res.getSymA()->getSymbol().isTemporary() ||
+ (Res.getSymA()->getSymbol().isELF() &&
+ cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
+ ELF::STB_LOCAL))) {
const MCExpr *CallExpr =
MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
@@ -2611,6 +2876,85 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
return false;
}
+ if (inPicMode() && ABI.ArePtrs64bit()) {
+ MCValue Res;
+ if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
+ Error(IDLoc, "expected relocatable expression");
+ return true;
+ }
+ if (Res.getSymB() != nullptr) {
+ Error(IDLoc, "expected relocatable expression with only one symbol");
+ return true;
+ }
+
+ // The case where the result register is $25 is somewhat special. If the
+ // symbol in the final relocation is external and not modified with a
+ // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT_DISP.
+ if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
+ Res.getConstant() == 0 &&
+ !(Res.getSymA()->getSymbol().isInSection() ||
+ Res.getSymA()->getSymbol().isTemporary() ||
+ (Res.getSymA()->getSymbol().isELF() &&
+ cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
+ 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);
+ return false;
+ }
+
+ // The remaining cases are:
+ // Small offset: ld $tmp, %got_disp(symbol)($gp)
+ // >daddiu $tmp, $tmp, offset
+ // >daddu $rd, $tmp, $rs
+ // The daddiu's marked with a '>' may be omitted if they are redundant. If
+ // this happens then the last instruction must use $rd as the result
+ // register.
+ const MipsMCExpr *GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP,
+ Res.getSymA(),
+ getContext());
+ const MCExpr *LoExpr = nullptr;
+ if (Res.getConstant() != 0) {
+ // Symbols fully resolve with just the %got_disp(symbol) but we
+ // must still account for any offset to the symbol for
+ // expressions like symbol+8.
+ LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
+
+ // FIXME: Offsets greater than 16 bits are not yet implemented.
+ // FIXME: The correct range is a 32-bit sign-extended number.
+ if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {
+ Error(IDLoc, "macro instruction uses large offset, which is not "
+ "currently supported");
+ return true;
+ }
+ }
+
+ unsigned TmpReg = DstReg;
+ if (UseSrcReg &&
+ getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
+ SrcReg)) {
+ // If $rs is the same as $rd, we need to use AT.
+ // If it is not available we exit.
+ unsigned ATReg = getATReg(IDLoc);
+ if (!ATReg)
+ return true;
+ TmpReg = ATReg;
+ }
+
+ TOut.emitRRX(Mips::LD, TmpReg, ABI.GetGlobalPtr(),
+ MCOperand::createExpr(GotExpr), IDLoc, STI);
+
+ if (LoExpr)
+ TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
+ IDLoc, STI);
+
+ if (UseSrcReg)
+ TOut.emitRRR(Mips::DADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
+
+ return false;
+ }
+
const MipsMCExpr *HiExpr =
MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
const MipsMCExpr *LoExpr =
@@ -2618,20 +2962,24 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
// This is the 64-bit symbol address expansion.
if (ABI.ArePtrs64bit() && isGP64bit()) {
- // We always need AT for the 64-bit expansion.
- // If it is not available we exit.
- unsigned ATReg = getATReg(IDLoc);
- if (!ATReg)
- return true;
+ // We need AT for the 64-bit expansion in the cases where the optional
+ // source register is the destination register and for the superscalar
+ // scheduled form.
+ //
+ // If it is not available we exit if the destination is the same as the
+ // source register.
const MipsMCExpr *HighestExpr =
MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
const MipsMCExpr *HigherExpr =
MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
- if (UseSrcReg &&
- getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
- SrcReg)) {
+ bool RdRegIsRsReg =
+ getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);
+
+ if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {
+ unsigned ATReg = getATReg(IDLoc);
+
// If $rs is the same as $rd:
// (d)la $rd, sym($rd) => lui $at, %highest(sym)
// daddiu $at, $at, %higher(sym)
@@ -2653,29 +3001,65 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
return false;
- }
+ } else if (canUseATReg() && !RdRegIsRsReg) {
+ unsigned ATReg = getATReg(IDLoc);
- // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
- // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
- // lui $at, %hi(sym)
- // daddiu $rd, $rd, %higher(sym)
- // daddiu $at, $at, %lo(sym)
- // dsll32 $rd, $rd, 0
- // daddu $rd, $rd, $at
- // (daddu $rd, $rd, $rs)
- TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
- STI);
- TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
- TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
- MCOperand::createExpr(HigherExpr), IDLoc, STI);
- TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
- IDLoc, STI);
- TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
- TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
- if (UseSrcReg)
- TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
+ // If the $rs is different from $rd or if $rs isn't specified and we
+ // have $at available:
+ // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
+ // lui $at, %hi(sym)
+ // daddiu $rd, $rd, %higher(sym)
+ // daddiu $at, $at, %lo(sym)
+ // dsll32 $rd, $rd, 0
+ // daddu $rd, $rd, $at
+ // (daddu $rd, $rd, $rs)
+ //
+ // Which is preferred for superscalar issue.
+ TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
+ STI);
+ TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
+ TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
+ MCOperand::createExpr(HigherExpr), IDLoc, STI);
+ TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
+ IDLoc, STI);
+ TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
+ TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
+ if (UseSrcReg)
+ TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
- return false;
+ return false;
+ } else if (!canUseATReg() && !RdRegIsRsReg) {
+ // Otherwise, synthesize the address in the destination register
+ // serially:
+ // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
+ // daddiu $rd, $rd, %higher(sym)
+ // dsll $rd, $rd, 16
+ // daddiu $rd, $rd, %hi(sym)
+ // dsll $rd, $rd, 16
+ // daddiu $rd, $rd, %lo(sym)
+ TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
+ STI);
+ TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
+ MCOperand::createExpr(HigherExpr), IDLoc, STI);
+ TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
+ TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
+ MCOperand::createExpr(HiExpr), IDLoc, STI);
+ TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
+ TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
+ MCOperand::createExpr(LoExpr), IDLoc, STI);
+ if (UseSrcReg)
+ TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
+
+ return false;
+ } else {
+ // We have a case where SrcReg == DstReg and we don't have $at
+ // available. We can't expand this case, so error out appropriately.
+ assert(SrcReg == DstReg && !canUseATReg() &&
+ "Could have expanded dla but didn't?");
+ reportParseError(IDLoc,
+ "pseudo-instruction requires $at, which is not available");
+ return true;
+ }
}
// And now, the 32-bit symbol address expansion:
@@ -2711,6 +3095,302 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
return false;
}
+// Each double-precision register DO-D15 overlaps with two of the single
+// precision registers F0-F31. As an example, all of the following hold true:
+// D0 + 1 == F1, F1 + 1 == D1, F1 + 1 == F2, depending on the context.
+static unsigned nextReg(unsigned Reg) {
+ if (MipsMCRegisterClasses[Mips::FGR32RegClassID].contains(Reg))
+ return Reg == (unsigned)Mips::F31 ? (unsigned)Mips::F0 : Reg + 1;
+ switch (Reg) {
+ default: llvm_unreachable("Unknown register in assembly macro expansion!");
+ case Mips::ZERO: return Mips::AT;
+ case Mips::AT: return Mips::V0;
+ case Mips::V0: return Mips::V1;
+ case Mips::V1: return Mips::A0;
+ case Mips::A0: return Mips::A1;
+ case Mips::A1: return Mips::A2;
+ case Mips::A2: return Mips::A3;
+ case Mips::A3: return Mips::T0;
+ case Mips::T0: return Mips::T1;
+ case Mips::T1: return Mips::T2;
+ case Mips::T2: return Mips::T3;
+ case Mips::T3: return Mips::T4;
+ case Mips::T4: return Mips::T5;
+ case Mips::T5: return Mips::T6;
+ case Mips::T6: return Mips::T7;
+ case Mips::T7: return Mips::S0;
+ case Mips::S0: return Mips::S1;
+ case Mips::S1: return Mips::S2;
+ case Mips::S2: return Mips::S3;
+ case Mips::S3: return Mips::S4;
+ case Mips::S4: return Mips::S5;
+ case Mips::S5: return Mips::S6;
+ case Mips::S6: return Mips::S7;
+ case Mips::S7: return Mips::T8;
+ case Mips::T8: return Mips::T9;
+ case Mips::T9: return Mips::K0;
+ case Mips::K0: return Mips::K1;
+ case Mips::K1: return Mips::GP;
+ case Mips::GP: return Mips::SP;
+ case Mips::SP: return Mips::FP;
+ case Mips::FP: return Mips::RA;
+ case Mips::RA: return Mips::ZERO;
+ case Mips::D0: return Mips::F1;
+ case Mips::D1: return Mips::F3;
+ case Mips::D2: return Mips::F5;
+ case Mips::D3: return Mips::F7;
+ case Mips::D4: return Mips::F9;
+ case Mips::D5: return Mips::F11;
+ case Mips::D6: return Mips::F13;
+ case Mips::D7: return Mips::F15;
+ case Mips::D8: return Mips::F17;
+ case Mips::D9: return Mips::F19;
+ case Mips::D10: return Mips::F21;
+ case Mips::D11: return Mips::F23;
+ case Mips::D12: return Mips::F25;
+ case Mips::D13: return Mips::F27;
+ case Mips::D14: return Mips::F29;
+ case Mips::D15: return Mips::F31;
+ }
+}
+
+// FIXME: This method is too general. In principle we should compute the number
+// of instructions required to synthesize the immediate inline compared to
+// synthesizing the address inline and relying on non .text sections.
+// For static O32 and N32 this may yield a small benefit, for static N64 this is
+// likely to yield a much larger benefit as we have to synthesize a 64bit
+// address to load a 64 bit value.
+bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc,
+ MCSymbol *Sym) {
+ unsigned ATReg = getATReg(IDLoc);
+ if (!ATReg)
+ return true;
+
+ if(IsPicEnabled) {
+ const MCExpr *GotSym =
+ MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
+ const MipsMCExpr *GotExpr =
+ MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext());
+
+ if(isABI_O32() || isABI_N32()) {
+ TOut.emitRRX(Mips::LW, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
+ IDLoc, STI);
+ } else { //isABI_N64()
+ TOut.emitRRX(Mips::LD, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
+ IDLoc, STI);
+ }
+ } else { //!IsPicEnabled
+ const MCExpr *HiSym =
+ MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
+ const MipsMCExpr *HiExpr =
+ MipsMCExpr::create(MipsMCExpr::MEK_HI, HiSym, getContext());
+
+ // FIXME: This is technically correct but gives a different result to gas,
+ // but gas is incomplete there (it has a fixme noting it doesn't work with
+ // 64-bit addresses).
+ // FIXME: With -msym32 option, the address expansion for N64 should probably
+ // use the O32 / N32 case. It's safe to use the 64 address expansion as the
+ // symbol's value is considered sign extended.
+ if(isABI_O32() || isABI_N32()) {
+ TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
+ } else { //isABI_N64()
+ const MCExpr *HighestSym =
+ MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
+ const MipsMCExpr *HighestExpr =
+ MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, HighestSym, getContext());
+ const MCExpr *HigherSym =
+ MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
+ const MipsMCExpr *HigherExpr =
+ MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, HigherSym, getContext());
+
+ TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
+ STI);
+ TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
+ MCOperand::createExpr(HigherExpr), IDLoc, STI);
+ TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
+ TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
+ IDLoc, STI);
+ TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
+ }
+ }
+ return false;
+}
+
+bool MipsAsmParser::expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR,
+ bool Is64FPU, SMLoc IDLoc,
+ MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
+ assert(Inst.getNumOperands() == 2 && "Invalid operand count");
+ assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
+ "Invalid instruction operand.");
+
+ unsigned FirstReg = Inst.getOperand(0).getReg();
+ uint64_t ImmOp64 = Inst.getOperand(1).getImm();
+
+ uint32_t HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
+ // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the
+ // exponent field), convert it to double (e.g. 1 to 1.0)
+ if ((HiImmOp64 & 0x7ff00000) == 0) {
+ APFloat RealVal(APFloat::IEEEdouble(), ImmOp64);
+ ImmOp64 = RealVal.bitcastToAPInt().getZExtValue();
+ }
+
+ uint32_t LoImmOp64 = ImmOp64 & 0xffffffff;
+ HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
+
+ if (IsSingle) {
+ // Conversion of a double in an uint64_t to a float in a uint32_t,
+ // retaining the bit pattern of a float.
+ uint32_t ImmOp32;
+ double doubleImm = BitsToDouble(ImmOp64);
+ float tmp_float = static_cast<float>(doubleImm);
+ ImmOp32 = FloatToBits(tmp_float);
+
+ if (IsGPR) {
+ if (loadImmediate(ImmOp32, FirstReg, Mips::NoRegister, true, true, IDLoc,
+ Out, STI))
+ return true;
+ return false;
+ } else {
+ unsigned ATReg = getATReg(IDLoc);
+ if (!ATReg)
+ return true;
+ if (LoImmOp64 == 0) {
+ if (loadImmediate(ImmOp32, ATReg, Mips::NoRegister, true, true, IDLoc,
+ Out, STI))
+ return true;
+ TOut.emitRR(Mips::MTC1, FirstReg, ATReg, IDLoc, STI);
+ return false;
+ }
+
+ MCSection *CS = getStreamer().getCurrentSectionOnly();
+ // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
+ // where appropriate.
+ MCSection *ReadOnlySection = getContext().getELFSection(
+ ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
+
+ MCSymbol *Sym = getContext().createTempSymbol();
+ const MCExpr *LoSym =
+ MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
+ const MipsMCExpr *LoExpr =
+ MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
+
+ getStreamer().SwitchSection(ReadOnlySection);
+ getStreamer().EmitLabel(Sym, IDLoc);
+ getStreamer().EmitIntValue(ImmOp32, 4);
+ getStreamer().SwitchSection(CS);
+
+ if(emitPartialAddress(TOut, IDLoc, Sym))
+ return true;
+ TOut.emitRRX(Mips::LWC1, FirstReg, ATReg,
+ MCOperand::createExpr(LoExpr), IDLoc, STI);
+ }
+ return false;
+ }
+
+ // if(!IsSingle)
+ unsigned ATReg = getATReg(IDLoc);
+ if (!ATReg)
+ return true;
+
+ if (IsGPR) {
+ if (LoImmOp64 == 0) {
+ if(isABI_N32() || isABI_N64()) {
+ if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, false, true,
+ IDLoc, Out, STI))
+ return true;
+ return false;
+ } else {
+ if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, true, true,
+ IDLoc, Out, STI))
+ return true;
+
+ if (loadImmediate(0, nextReg(FirstReg), Mips::NoRegister, true, true,
+ IDLoc, Out, STI))
+ return true;
+ return false;
+ }
+ }
+
+ MCSection *CS = getStreamer().getCurrentSectionOnly();
+ MCSection *ReadOnlySection = getContext().getELFSection(
+ ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
+
+ MCSymbol *Sym = getContext().createTempSymbol();
+ const MCExpr *LoSym =
+ MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
+ const MipsMCExpr *LoExpr =
+ MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
+
+ getStreamer().SwitchSection(ReadOnlySection);
+ getStreamer().EmitLabel(Sym, IDLoc);
+ getStreamer().EmitIntValue(HiImmOp64, 4);
+ getStreamer().EmitIntValue(LoImmOp64, 4);
+ getStreamer().SwitchSection(CS);
+
+ if(emitPartialAddress(TOut, IDLoc, Sym))
+ return true;
+ if(isABI_N64())
+ TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
+ MCOperand::createExpr(LoExpr), IDLoc, STI);
+ else
+ TOut.emitRRX(Mips::ADDiu, ATReg, ATReg,
+ MCOperand::createExpr(LoExpr), IDLoc, STI);
+
+ if(isABI_N32() || isABI_N64())
+ TOut.emitRRI(Mips::LD, FirstReg, ATReg, 0, IDLoc, STI);
+ else {
+ TOut.emitRRI(Mips::LW, FirstReg, ATReg, 0, IDLoc, STI);
+ TOut.emitRRI(Mips::LW, nextReg(FirstReg), ATReg, 4, IDLoc, STI);
+ }
+ return false;
+ } else { // if(!IsGPR && !IsSingle)
+ if ((LoImmOp64 == 0) &&
+ !((HiImmOp64 & 0xffff0000) && (HiImmOp64 & 0x0000ffff))) {
+ // FIXME: In the case where the constant is zero, we can load the
+ // register directly from the zero register.
+ if (loadImmediate(HiImmOp64, ATReg, Mips::NoRegister, true, true, IDLoc,
+ Out, STI))
+ return true;
+ if (isABI_N32() || isABI_N64())
+ TOut.emitRR(Mips::DMTC1, FirstReg, ATReg, IDLoc, STI);
+ else if (hasMips32r2()) {
+ TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
+ TOut.emitRRR(Mips::MTHC1_D32, FirstReg, FirstReg, ATReg, IDLoc, STI);
+ } else {
+ TOut.emitRR(Mips::MTC1, nextReg(FirstReg), ATReg, IDLoc, STI);
+ TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
+ }
+ return false;
+ }
+
+ MCSection *CS = getStreamer().getCurrentSectionOnly();
+ // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
+ // where appropriate.
+ MCSection *ReadOnlySection = getContext().getELFSection(
+ ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
+
+ MCSymbol *Sym = getContext().createTempSymbol();
+ const MCExpr *LoSym =
+ MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
+ const MipsMCExpr *LoExpr =
+ MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
+
+ getStreamer().SwitchSection(ReadOnlySection);
+ getStreamer().EmitLabel(Sym, IDLoc);
+ getStreamer().EmitIntValue(HiImmOp64, 4);
+ getStreamer().EmitIntValue(LoImmOp64, 4);
+ getStreamer().SwitchSection(CS);
+
+ if(emitPartialAddress(TOut, IDLoc, Sym))
+ return true;
+ TOut.emitRRX(Is64FPU ? Mips::LDC164 : Mips::LDC1, FirstReg, ATReg,
+ MCOperand::createExpr(LoExpr), IDLoc, STI);
+ }
+ return false;
+}
+
bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
MCStreamer &Out,
const MCSubtargetInfo *STI) {
@@ -2769,6 +3449,8 @@ bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
"expected immediate or expression operand");
+ bool IsLikely = false;
+
unsigned OpCode = 0;
switch(Inst.getOpcode()) {
case Mips::BneImm:
@@ -2777,16 +3459,29 @@ bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
case Mips::BeqImm:
OpCode = Mips::BEQ;
break;
+ case Mips::BEQLImmMacro:
+ OpCode = Mips::BEQL;
+ IsLikely = true;
+ break;
+ case Mips::BNELImmMacro:
+ OpCode = Mips::BNEL;
+ IsLikely = true;
+ break;
default:
llvm_unreachable("Unknown immediate branch pseudo-instruction.");
break;
}
int64_t ImmValue = ImmOp.getImm();
- if (ImmValue == 0)
- TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
- STI);
- else {
+ if (ImmValue == 0) {
+ if (IsLikely) {
+ TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO,
+ MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
+ TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
+ } else
+ TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
+ STI);
+ } else {
warnIfNoMacro(IDLoc);
unsigned ATReg = getATReg(IDLoc);
@@ -2797,7 +3492,12 @@ bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
IDLoc, Out, STI))
return true;
- TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
+ if (IsLikely) {
+ TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg,
+ MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
+ TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
+ } else
+ TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
}
return false;
}
@@ -2904,9 +3604,9 @@ bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
unsigned Opcode = Inst.getOpcode();
unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
- assert (Inst.getOperand(OpNum - 1).isImm() &&
- Inst.getOperand(OpNum - 2).isReg() &&
- Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
+ assert(Inst.getOperand(OpNum - 1).isImm() &&
+ Inst.getOperand(OpNum - 2).isReg() &&
+ Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
Inst.getOperand(OpNum - 1).getImm() >= 0 &&
@@ -3185,6 +3885,14 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
return false;
}
+// Expand a integer division macro.
+//
+// Notably we don't have to emit a warning when encountering $rt as the $zero
+// register, or 0 as an immediate. processInstruction() has already done that.
+//
+// The destination register can only be $zero when expanding (S)DivIMacro or
+// D(S)DivMacro.
+
bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
const MCSubtargetInfo *STI, const bool IsMips64,
const bool Signed) {
@@ -3200,67 +3908,88 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
assert(RsRegOp.isReg() && "expected register operand kind");
unsigned RsReg = RsRegOp.getReg();
- const MCOperand &RtRegOp = Inst.getOperand(2);
- assert(RtRegOp.isReg() && "expected register operand kind");
- unsigned RtReg = RtRegOp.getReg();
+ unsigned RtReg;
+ int64_t ImmValue;
+
+ const MCOperand &RtOp = Inst.getOperand(2);
+ assert((RtOp.isReg() || RtOp.isImm()) &&
+ "expected register or immediate operand kind");
+ if (RtOp.isReg())
+ RtReg = RtOp.getReg();
+ else
+ ImmValue = RtOp.getImm();
+
unsigned DivOp;
unsigned ZeroReg;
+ unsigned SubOp;
if (IsMips64) {
DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
ZeroReg = Mips::ZERO_64;
+ SubOp = Mips::DSUB;
} else {
DivOp = Signed ? Mips::SDIV : Mips::UDIV;
ZeroReg = Mips::ZERO;
+ SubOp = Mips::SUB;
}
bool UseTraps = useTraps();
- if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
- if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
- Warning(IDLoc, "dividing zero by zero");
- if (IsMips64) {
- if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
- if (UseTraps) {
- TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
- return false;
- }
+ if (RtOp.isImm()) {
+ unsigned ATReg = getATReg(IDLoc);
+ if (!ATReg)
+ return true;
+ if (ImmValue == 0) {
+ if (UseTraps)
+ TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
+ else
TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
- return false;
- }
+ return false;
+ }
+
+ if (ImmValue == 1) {
+ TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
+ return false;
+ } else if (Signed && ImmValue == -1) {
+ TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
+ return false;
} else {
- TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
+ if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
+ false, Inst.getLoc(), Out, STI))
+ return true;
+ TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
+ TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
return false;
}
+ return true;
}
+ // If the macro expansion of (d)div(u) would always trap or break, insert
+ // the trap/break and exit. This gives a different result to GAS. GAS has
+ // an inconsistency/missed optimization in that not all cases are handled
+ // equivalently. As the observed behaviour is the same, we're ok.
if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
- Warning(IDLoc, "division by zero");
- if (Signed) {
- if (UseTraps) {
- TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
- return false;
- }
-
- TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
+ if (UseTraps) {
+ TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
return false;
}
+ TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
+ return false;
}
- // FIXME: The values for these two BranchTarget variables may be different in
- // micromips. These magic numbers need to be removed.
- unsigned BranchTargetNoTraps;
- unsigned BranchTarget;
+ // Temporary label for first branch traget
+ MCContext &Context = TOut.getStreamer().getContext();
+ MCSymbol *BrTarget;
+ MCOperand LabelOp;
if (UseTraps) {
- BranchTarget = IsMips64 ? 12 : 8;
TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
} else {
- BranchTarget = IsMips64 ? 20 : 16;
- BranchTargetNoTraps = 8;
// Branch to the li instruction.
- TOut.emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc, STI);
+ BrTarget = Context.createTempSymbol();
+ LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
+ TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI);
}
TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
@@ -3269,6 +3998,9 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
if (!Signed) {
+ if (!UseTraps)
+ TOut.getStreamer().EmitLabel(BrTarget);
+
TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
return false;
}
@@ -3277,15 +4009,23 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
if (!ATReg)
return true;
+ if (!UseTraps)
+ TOut.getStreamer().EmitLabel(BrTarget);
+
TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
+
+ // Temporary label for the second branch target.
+ MCSymbol *BrTargetEnd = Context.createTempSymbol();
+ MCOperand LabelOpEnd =
+ MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context));
+
+ // Branch to the mflo instruction.
+ TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI);
+
if (IsMips64) {
- // Branch to the mflo instruction.
- TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
} else {
- // Branch to the mflo instruction.
- TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
}
@@ -3293,10 +4033,12 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
else {
// Branch to the mflo instruction.
- TOut.emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, STI);
+ TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
}
+
+ TOut.getStreamer().EmitLabel(BrTargetEnd);
TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
return false;
}
@@ -3503,10 +4245,10 @@ bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
const MCSubtargetInfo *STI) {
MipsTargetStreamer &TOut = getTargetStreamer();
- assert (Inst.getNumOperands() == 3 && "Invalid operand count");
- assert (Inst.getOperand(0).isReg() &&
- Inst.getOperand(1).isReg() &&
- Inst.getOperand(2).isImm() && "Invalid instruction operand.");
+ assert(Inst.getNumOperands() == 3 && "Invalid operand count");
+ assert(Inst.getOperand(0).isReg() &&
+ Inst.getOperand(1).isReg() &&
+ Inst.getOperand(2).isImm() && "Invalid instruction operand.");
unsigned ATReg = Mips::NoRegister;
unsigned FinalDstReg = Mips::NoRegister;
@@ -3514,7 +4256,7 @@ bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
unsigned SrcReg = Inst.getOperand(1).getReg();
int64_t ImmValue = Inst.getOperand(2).getImm();
- bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
+ bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue));
unsigned FinalOpcode = Inst.getOpcode();
@@ -3530,30 +4272,69 @@ bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
switch (FinalOpcode) {
default:
llvm_unreachable("unimplemented expansion");
- case (Mips::ADDi):
+ case Mips::ADDi:
FinalOpcode = Mips::ADD;
break;
- case (Mips::ADDiu):
+ case Mips::ADDiu:
FinalOpcode = Mips::ADDu;
break;
- case (Mips::ANDi):
+ case Mips::ANDi:
FinalOpcode = Mips::AND;
break;
- case (Mips::NORImm):
+ case Mips::NORImm:
FinalOpcode = Mips::NOR;
break;
- case (Mips::ORi):
+ case Mips::ORi:
FinalOpcode = Mips::OR;
break;
- case (Mips::SLTi):
+ case Mips::SLTi:
FinalOpcode = Mips::SLT;
break;
- case (Mips::SLTiu):
+ case Mips::SLTiu:
FinalOpcode = Mips::SLTu;
break;
- case (Mips::XORi):
+ case Mips::XORi:
FinalOpcode = Mips::XOR;
break;
+ case Mips::ADDi_MM:
+ FinalOpcode = Mips::ADD_MM;
+ break;
+ case Mips::ADDiu_MM:
+ FinalOpcode = Mips::ADDu_MM;
+ break;
+ case Mips::ANDi_MM:
+ FinalOpcode = Mips::AND_MM;
+ break;
+ case Mips::ORi_MM:
+ FinalOpcode = Mips::OR_MM;
+ break;
+ case Mips::SLTi_MM:
+ FinalOpcode = Mips::SLT_MM;
+ break;
+ case Mips::SLTiu_MM:
+ FinalOpcode = Mips::SLTu_MM;
+ break;
+ case Mips::XORi_MM:
+ FinalOpcode = Mips::XOR_MM;
+ break;
+ case Mips::ANDi64:
+ FinalOpcode = Mips::AND64;
+ break;
+ case Mips::NORImm64:
+ FinalOpcode = Mips::NOR64;
+ break;
+ case Mips::ORi64:
+ FinalOpcode = Mips::OR64;
+ break;
+ case Mips::SLTImm64:
+ FinalOpcode = Mips::SLT64;
+ break;
+ case Mips::SLTUImm64:
+ FinalOpcode = Mips::SLTu64;
+ break;
+ case Mips::XORi64:
+ FinalOpcode = Mips::XOR64;
+ break;
}
if (FinalDstReg == Mips::NoRegister)
@@ -3578,7 +4359,6 @@ bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
unsigned SecondShift = Mips::NOP;
if (hasMips32r2()) {
-
if (DReg == SReg) {
TmpReg = getATReg(Inst.getLoc());
if (!TmpReg)
@@ -3600,7 +4380,6 @@ bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
}
if (hasMips32()) {
-
switch (Inst.getOpcode()) {
default:
llvm_unreachable("unexpected instruction opcode");
@@ -3642,7 +4421,6 @@ bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
unsigned SecondShift = Mips::NOP;
if (hasMips32r2()) {
-
if (Inst.getOpcode() == Mips::ROLImm) {
uint64_t MaxShift = 32;
uint64_t ShiftValue = ImmValue;
@@ -3661,7 +4439,6 @@ bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
}
if (hasMips32()) {
-
if (ImmValue == 0) {
TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
return false;
@@ -3707,7 +4484,6 @@ bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
unsigned SecondShift = Mips::NOP;
if (hasMips64r2()) {
-
if (TmpReg == SReg) {
TmpReg = getATReg(Inst.getLoc());
if (!TmpReg)
@@ -3729,7 +4505,6 @@ bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
}
if (hasMips64()) {
-
switch (Inst.getOpcode()) {
default:
llvm_unreachable("unexpected instruction opcode");
@@ -3773,7 +4548,6 @@ bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
MCInst TmpInst;
if (hasMips64r2()) {
-
unsigned FinalOpcode = Mips::NOP;
if (ImmValue == 0)
FinalOpcode = Mips::DROTR;
@@ -3801,7 +4575,6 @@ bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
}
if (hasMips64()) {
-
if (ImmValue == 0) {
TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
return false;
@@ -3871,43 +4644,117 @@ bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
return false;
}
-static unsigned nextReg(unsigned Reg) {
- switch (Reg) {
- case Mips::ZERO: return Mips::AT;
- case Mips::AT: return Mips::V0;
- case Mips::V0: return Mips::V1;
- case Mips::V1: return Mips::A0;
- case Mips::A0: return Mips::A1;
- case Mips::A1: return Mips::A2;
- case Mips::A2: return Mips::A3;
- case Mips::A3: return Mips::T0;
- case Mips::T0: return Mips::T1;
- case Mips::T1: return Mips::T2;
- case Mips::T2: return Mips::T3;
- case Mips::T3: return Mips::T4;
- case Mips::T4: return Mips::T5;
- case Mips::T5: return Mips::T6;
- case Mips::T6: return Mips::T7;
- case Mips::T7: return Mips::S0;
- case Mips::S0: return Mips::S1;
- case Mips::S1: return Mips::S2;
- case Mips::S2: return Mips::S3;
- case Mips::S3: return Mips::S4;
- case Mips::S4: return Mips::S5;
- case Mips::S5: return Mips::S6;
- case Mips::S6: return Mips::S7;
- case Mips::S7: return Mips::T8;
- case Mips::T8: return Mips::T9;
- case Mips::T9: return Mips::K0;
- case Mips::K0: return Mips::K1;
- case Mips::K1: return Mips::GP;
- case Mips::GP: return Mips::SP;
- case Mips::SP: return Mips::FP;
- case Mips::FP: return Mips::RA;
- case Mips::RA: return Mips::ZERO;
- default: return 0;
+bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
+ unsigned ATReg = Mips::NoRegister;
+ unsigned DstReg = Inst.getOperand(0).getReg();
+ unsigned SrcReg = Inst.getOperand(1).getReg();
+ int32_t ImmValue = Inst.getOperand(2).getImm();
+
+ ATReg = getATReg(IDLoc);
+ if (!ATReg)
+ return true;
+
+ loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out, STI);
+
+ TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT,
+ SrcReg, ATReg, IDLoc, STI);
+
+ TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
+
+ return false;
+}
+
+bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
+ unsigned ATReg = Mips::NoRegister;
+ unsigned DstReg = Inst.getOperand(0).getReg();
+ unsigned SrcReg = Inst.getOperand(1).getReg();
+ unsigned TmpReg = Inst.getOperand(2).getReg();
+
+ ATReg = getATReg(Inst.getLoc());
+ if (!ATReg)
+ return true;
+
+ TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT,
+ SrcReg, TmpReg, IDLoc, STI);
+
+ TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
+
+ TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32,
+ DstReg, DstReg, 0x1F, IDLoc, STI);
+
+ TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
+
+ if (useTraps()) {
+ TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI);
+ } else {
+ MCContext & Context = TOut.getStreamer().getContext();
+ MCSymbol * BrTarget = Context.createTempSymbol();
+ MCOperand LabelOp =
+ MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
+
+ TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI);
+ if (AssemblerOptions.back()->isReorder())
+ TOut.emitNop(IDLoc, STI);
+ TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
+
+ TOut.getStreamer().EmitLabel(BrTarget);
+ }
+ TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
+
+ return false;
+}
+
+bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
+ unsigned ATReg = Mips::NoRegister;
+ unsigned DstReg = Inst.getOperand(0).getReg();
+ unsigned SrcReg = Inst.getOperand(1).getReg();
+ unsigned TmpReg = Inst.getOperand(2).getReg();
+
+ ATReg = getATReg(IDLoc);
+ if (!ATReg)
+ return true;
+
+ TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu,
+ SrcReg, TmpReg, IDLoc, STI);
+
+ TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
+ TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
+ if (useTraps()) {
+ TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI);
+ } else {
+ MCContext & Context = TOut.getStreamer().getContext();
+ MCSymbol * BrTarget = Context.createTempSymbol();
+ MCOperand LabelOp =
+ MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
+
+ TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI);
+ if (AssemblerOptions.back()->isReorder())
+ TOut.emitNop(IDLoc, STI);
+ TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
+
+ TOut.getStreamer().EmitLabel(BrTarget);
}
+ return false;
+}
+
+bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
+ unsigned DstReg = Inst.getOperand(0).getReg();
+ unsigned SrcReg = Inst.getOperand(1).getReg();
+ unsigned TmpReg = Inst.getOperand(2).getReg();
+
+ TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI);
+ TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
+
+ return false;
}
// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
@@ -3985,7 +4832,6 @@ bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
const MCSubtargetInfo *STI) {
-
warnIfNoMacro(IDLoc);
MipsTargetStreamer &TOut = getTargetStreamer();
@@ -4158,17 +5004,15 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
MCStreamer &Out,
uint64_t &ErrorInfo,
bool MatchingInlineAsm) {
-
MCInst Inst;
unsigned MatchResult =
MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
switch (MatchResult) {
- case Match_Success: {
+ case Match_Success:
if (processInstruction(Inst, IDLoc, Out, STI))
return true;
return false;
- }
case Match_MissingFeature:
Error(IDLoc, "instruction requires a CPU feature not currently enabled");
return true;
@@ -4353,7 +5197,7 @@ int MipsAsmParser::matchCPURegisterName(StringRef Name) {
CC = StringSwitch<unsigned>(Name)
.Case("zero", 0)
- .Case("at", 1)
+ .Cases("at", "AT", 1)
.Case("a0", 4)
.Case("a1", 5)
.Case("a2", 6)
@@ -4441,7 +5285,6 @@ int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
}
int MipsAsmParser::matchFPURegisterName(StringRef Name) {
-
if (Name[0] == 'f') {
StringRef NumString = Name.substr(1);
unsigned IntVal;
@@ -4455,7 +5298,6 @@ int MipsAsmParser::matchFPURegisterName(StringRef Name) {
}
int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
-
if (Name.startswith("fcc")) {
StringRef NumString = Name.substr(3);
unsigned IntVal;
@@ -4469,7 +5311,6 @@ int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
}
int MipsAsmParser::matchACRegisterName(StringRef Name) {
-
if (Name.startswith("ac")) {
StringRef NumString = Name.substr(2);
unsigned IntVal;
@@ -4511,6 +5352,10 @@ int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
return CC;
}
+bool MipsAsmParser::canUseATReg() {
+ return AssemblerOptions.back()->getATRegIndex() != 0;
+}
+
unsigned MipsAsmParser::getATReg(SMLoc Loc) {
unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
if (ATIndex == 0) {
@@ -4589,7 +5434,6 @@ bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
}
bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
-
switch (Expr->getKind()) {
case MCExpr::Constant:
return true;
@@ -5491,6 +6335,39 @@ bool MipsAsmParser::parseSetNoOddSPRegDirective() {
return false;
}
+bool MipsAsmParser::parseSetMtDirective() {
+ MCAsmParser &Parser = getParser();
+ Parser.Lex(); // Eat "mt".
+
+ // 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;
+ }
+
+ setFeatureBits(Mips::FeatureMT, "mt");
+ getTargetStreamer().emitDirectiveSetMt();
+ Parser.Lex(); // Consume the EndOfStatement.
+ return false;
+}
+
+bool MipsAsmParser::parseSetNoMtDirective() {
+ MCAsmParser &Parser = getParser();
+ Parser.Lex(); // Eat "nomt".
+
+ // 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;
+ }
+
+ clearFeatureBits(Mips::FeatureMT, "mt");
+
+ getTargetStreamer().emitDirectiveSetNoMt();
+ Parser.Lex(); // Consume the EndOfStatement.
+ return false;
+}
+
bool MipsAsmParser::parseSetPopDirective() {
MCAsmParser &Parser = getParser();
SMLoc Loc = getLexer().getLoc();
@@ -5522,7 +6399,7 @@ bool MipsAsmParser::parseSetPushDirective() {
// Create a copy of the current assembler options environment and push it.
AssemblerOptions.push_back(
- make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
+ llvm::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
getTargetStreamer().emitDirectiveSetPush();
return false;
@@ -5914,6 +6791,14 @@ bool MipsAsmParser::parseDirectiveSet() {
return parseSetAtDirective();
} else if (Tok.getString() == "arch") {
return parseSetArchDirective();
+ } else if (Tok.getString() == "bopt") {
+ Warning(Tok.getLoc(), "'bopt' feature is unsupported");
+ getParser().Lex();
+ return false;
+ } else if (Tok.getString() == "nobopt") {
+ // We're already running in nobopt mode, so nothing to do.
+ getParser().Lex();
+ return false;
} else if (Tok.getString() == "fp") {
return parseSetFpDirective();
} else if (Tok.getString() == "oddspreg") {
@@ -5983,6 +6868,10 @@ bool MipsAsmParser::parseDirectiveSet() {
return parseSetMsaDirective();
} else if (Tok.getString() == "nomsa") {
return parseSetNoMsaDirective();
+ } else if (Tok.getString() == "mt") {
+ return parseSetMtDirective();
+ } else if (Tok.getString() == "nomt") {
+ return parseSetNoMtDirective();
} else if (Tok.getString() == "softfloat") {
return parseSetSoftFloatDirective();
} else if (Tok.getString() == "hardfloat") {
@@ -6001,7 +6890,7 @@ bool MipsAsmParser::parseDirectiveSet() {
bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
MCAsmParser &Parser = getParser();
if (getLexer().isNot(AsmToken::EndOfStatement)) {
- for (;;) {
+ while (true) {
const MCExpr *Value;
if (getParser().parseExpression(Value))
return true;
@@ -6191,6 +7080,23 @@ bool MipsAsmParser::parseInsnDirective() {
return false;
}
+/// parseRSectionDirective
+/// ::= .rdata
+bool MipsAsmParser::parseRSectionDirective(StringRef Section) {
+ // 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;
+ }
+
+ MCSection *ELFSection = getContext().getELFSection(
+ Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
+ getParser().getStreamer().SwitchSection(ELFSection);
+
+ getParser().Lex(); // Eat EndOfStatement token.
+ return false;
+}
+
/// parseSSectionDirective
/// ::= .sbss
/// ::= .sdata
@@ -6215,6 +7121,7 @@ bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
/// ::= .module fp=value
/// ::= .module softfloat
/// ::= .module hardfloat
+/// ::= .module mt
bool MipsAsmParser::parseDirectiveModule() {
MCAsmParser &Parser = getParser();
MCAsmLexer &Lexer = getLexer();
@@ -6314,6 +7221,25 @@ bool MipsAsmParser::parseDirectiveModule() {
}
return false; // parseDirectiveModule has finished successfully.
+ } else if (Option == "mt") {
+ setModuleFeatureBits(Mips::FeatureMT, "mt");
+
+ // Synchronize the ABI Flags information with the FeatureBits information we
+ // updated above.
+ getTargetStreamer().updateABIInfo(*this);
+
+ // If printing assembly, use the recently updated ABI Flags information.
+ // If generating ELF, don't do anything (the .MIPS.abiflags section gets
+ // emitted later).
+ getTargetStreamer().emitDirectiveModuleMT();
+
+ // 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;
+ }
+
+ return false; // parseDirectiveModule has finished successfully.
} else {
return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
}
@@ -6738,6 +7664,10 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
parseInsnDirective();
return false;
}
+ if (IDVal == ".rdata") {
+ parseRSectionDirective(".rodata");
+ return false;
+ }
if (IDVal == ".sbss") {
parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
return false;
@@ -6773,3 +7703,15 @@ extern "C" void LLVMInitializeMipsAsmParser() {
#define GET_REGISTER_MATCHER
#define GET_MATCHER_IMPLEMENTATION
#include "MipsGenAsmMatcher.inc"
+
+bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
+ // Find the appropriate table for this asm variant.
+ const MatchEntry *Start, *End;
+ switch (VariantID) {
+ default: llvm_unreachable("invalid variant!");
+ case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break;
+ }
+ // Search the table.
+ auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());
+ return MnemonicRange.first != MnemonicRange.second;
+}
diff --git a/contrib/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/contrib/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
index f80efb1..b0b9943 100644
--- a/contrib/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
+++ b/contrib/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
@@ -1,4 +1,4 @@
-//===- MipsDisassembler.cpp - Disassembler for Mips -------------*- C++ -*-===//
+//===- MipsDisassembler.cpp - Disassembler for Mips -----------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,15 +12,21 @@
//===----------------------------------------------------------------------===//
#include "Mips.h"
-#include "MipsRegisterInfo.h"
-#include "MipsSubtarget.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCFixedLenDisassembler.h"
#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <cstdint>
using namespace llvm;
@@ -33,6 +39,7 @@ namespace {
class MipsDisassembler : public MCDisassembler {
bool IsMicroMips;
bool IsBigEndian;
+
public:
MipsDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, bool IsBigEndian)
: MCDisassembler(STI, Ctx),
@@ -42,9 +49,11 @@ public:
bool hasMips2() const { return STI.getFeatureBits()[Mips::FeatureMips2]; }
bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; }
bool hasMips32() const { return STI.getFeatureBits()[Mips::FeatureMips32]; }
+
bool hasMips32r6() const {
return STI.getFeatureBits()[Mips::FeatureMips32r6];
}
+
bool isFP64() const { return STI.getFeatureBits()[Mips::FeatureFP64Bit]; }
bool isGP64() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; }
@@ -527,11 +536,13 @@ static DecodeStatus DecodeMovePRegPair(MCInst &Inst, unsigned Insn,
const void *Decoder);
namespace llvm {
+
Target &getTheMipselTarget();
Target &getTheMipsTarget();
Target &getTheMips64Target();
Target &getTheMips64elTarget();
-}
+
+} // end namespace llvm
static MCDisassembler *createMipsDisassembler(
const Target &T,
@@ -1106,6 +1117,7 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
raw_ostream &CStream) const {
uint32_t Insn;
DecodeStatus Result;
+ Size = 0;
if (IsMicroMips) {
Result = readInstruction16(Bytes, Address, Size, Insn, IsBigEndian);
@@ -1168,98 +1180,88 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
}
}
- // This is an invalid instruction. Let the disassembler move forward by the
- // minimum instruction size.
+ // This is an invalid instruction. Claim that the Size is 2 bytes. Since
+ // microMIPS instructions have a minimum alignment of 2, the next 2 bytes
+ // could form a valid instruction. The two bytes we rejected as an
+ // instruction could have actually beeen an inline constant pool that is
+ // unconditionally branched over.
Size = 2;
return MCDisassembler::Fail;
}
+ // Attempt to read the instruction so that we can attempt to decode it. If
+ // the buffer is not 4 bytes long, let the higher level logic figure out
+ // what to do with a size of zero and MCDisassembler::Fail.
Result = readInstruction32(Bytes, Address, Size, Insn, IsBigEndian, false);
- if (Result == MCDisassembler::Fail) {
- Size = 4;
+ if (Result == MCDisassembler::Fail)
return MCDisassembler::Fail;
- }
+
+ // The only instruction size for standard encoded MIPS.
+ Size = 4;
if (hasCOP3()) {
DEBUG(dbgs() << "Trying COP3_ table (32-bit opcodes):\n");
Result =
decodeInstruction(DecoderTableCOP3_32, Instr, Insn, Address, this, STI);
- if (Result != MCDisassembler::Fail) {
- Size = 4;
+ if (Result != MCDisassembler::Fail)
return Result;
- }
}
if (hasMips32r6() && isGP64()) {
DEBUG(dbgs() << "Trying Mips32r6_64r6 (GPR64) table (32-bit opcodes):\n");
Result = decodeInstruction(DecoderTableMips32r6_64r6_GP6432, Instr, Insn,
Address, this, STI);
- if (Result != MCDisassembler::Fail) {
- Size = 4;
+ if (Result != MCDisassembler::Fail)
return Result;
- }
}
if (hasMips32r6() && isPTR64()) {
DEBUG(dbgs() << "Trying Mips32r6_64r6 (PTR64) table (32-bit opcodes):\n");
Result = decodeInstruction(DecoderTableMips32r6_64r6_PTR6432, Instr, Insn,
Address, this, STI);
- if (Result != MCDisassembler::Fail) {
- Size = 4;
+ if (Result != MCDisassembler::Fail)
return Result;
- }
}
if (hasMips32r6()) {
DEBUG(dbgs() << "Trying Mips32r6_64r6 table (32-bit opcodes):\n");
Result = decodeInstruction(DecoderTableMips32r6_64r632, Instr, Insn,
Address, this, STI);
- if (Result != MCDisassembler::Fail) {
- Size = 4;
+ if (Result != MCDisassembler::Fail)
return Result;
- }
}
if (hasMips2() && isPTR64()) {
DEBUG(dbgs() << "Trying Mips32r6_64r6 (PTR64) table (32-bit opcodes):\n");
Result = decodeInstruction(DecoderTableMips32_64_PTR6432, Instr, Insn,
Address, this, STI);
- if (Result != MCDisassembler::Fail) {
- Size = 4;
+ if (Result != MCDisassembler::Fail)
return Result;
- }
}
if (hasCnMips()) {
DEBUG(dbgs() << "Trying CnMips table (32-bit opcodes):\n");
Result = decodeInstruction(DecoderTableCnMips32, Instr, Insn,
Address, this, STI);
- if (Result != MCDisassembler::Fail) {
- Size = 4;
+ if (Result != MCDisassembler::Fail)
return Result;
- }
}
if (isGP64()) {
DEBUG(dbgs() << "Trying Mips64 (GPR64) table (32-bit opcodes):\n");
Result = decodeInstruction(DecoderTableMips6432, Instr, Insn,
Address, this, STI);
- if (Result != MCDisassembler::Fail) {
- Size = 4;
+ if (Result != MCDisassembler::Fail)
return Result;
- }
}
DEBUG(dbgs() << "Trying Mips table (32-bit opcodes):\n");
// Calling the auto-generated decoder function.
Result =
decodeInstruction(DecoderTableMips32, Instr, Insn, Address, this, STI);
- if (Result != MCDisassembler::Fail) {
- Size = 4;
+ if (Result != MCDisassembler::Fail)
return Result;
- }
- Size = 4;
return MCDisassembler::Fail;
}
@@ -1267,16 +1269,13 @@ static DecodeStatus DecodeCPU16RegsRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder) {
-
return MCDisassembler::Fail;
-
}
static DecodeStatus DecodeGPR64RegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder) {
-
if (RegNo > 31)
return MCDisassembler::Fail;
@@ -1620,7 +1619,7 @@ static DecodeStatus DecodeMSA128Mem(MCInst &Inst, unsigned Insn,
switch(Inst.getOpcode())
{
default:
- assert (0 && "Unexpected instruction");
+ assert(false && "Unexpected instruction");
return MCDisassembler::Fail;
break;
case Mips::LD_B:
@@ -1980,7 +1979,6 @@ static DecodeStatus DecodeAFGR64RegisterClass(MCInst &Inst,
if (RegNo > 30 || RegNo %2)
return MCDisassembler::Fail;
- ;
unsigned Reg = getReg(Decoder, Mips::AFGR64RegClassID, RegNo /2);
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
@@ -2128,7 +2126,6 @@ static DecodeStatus DecodeJumpTarget(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder) {
-
unsigned JumpOffset = fieldFromInstruction(Insn, 0, 26) << 2;
Inst.addOperand(MCOperand::createImm(JumpOffset));
return MCDisassembler::Success;
@@ -2267,7 +2264,14 @@ static DecodeStatus DecodeInsSize(MCInst &Inst,
const void *Decoder) {
// First we need to grab the pos(lsb) from MCInst.
int Pos = Inst.getOperand(2).getImm();
- int Size = (int) Insn - Pos + 1;
+ if (Inst.getOpcode() == Mips::DINSU)
+ Pos += 32;
+ int Size;
+ if (Inst.getOpcode() == Mips::DINSM ||
+ Inst.getOpcode() == Mips::DINSU)
+ Size = (int) Insn - Pos + 33;
+ else
+ Size = (int) Insn - Pos + 1;
Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Size)));
return MCDisassembler::Success;
}
@@ -2363,7 +2367,6 @@ static DecodeStatus DecodeRegListOperand16(MCInst &Inst, unsigned Insn,
static DecodeStatus DecodeMovePRegPair(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
-
unsigned RegPair = fieldFromInstruction(Insn, 7, 3);
switch (RegPair) {
diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp
index 932d38a..4a2b75b 100644
--- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp
+++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp
@@ -1,4 +1,4 @@
-//===-- MipsABIFlagsSection.cpp - Mips ELF ABI Flags Section ---*- C++ -*--===//
+//===- MipsABIFlagsSection.cpp - Mips ELF ABI Flags Section ---------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,7 +7,11 @@
//
//===----------------------------------------------------------------------===//
-#include "MipsABIFlagsSection.h"
+#include "MCTargetDesc/MipsABIFlagsSection.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MipsABIFlags.h"
using namespace llvm;
@@ -51,6 +55,7 @@ uint8_t MipsABIFlagsSection::getCPR1SizeValue() {
}
namespace llvm {
+
MCStreamer &operator<<(MCStreamer &OS, MipsABIFlagsSection &ABIFlagsSection) {
// Write out a Elf_Internal_ABIFlags_v0 struct
OS.EmitIntValue(ABIFlagsSection.getVersionValue(), 2); // version
@@ -66,4 +71,5 @@ MCStreamer &operator<<(MCStreamer &OS, MipsABIFlagsSection &ABIFlagsSection) {
OS.EmitIntValue(ABIFlagsSection.getFlags2Value(), 4); // flags2
return OS;
}
-}
+
+} // end namespace llvm
diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h
index 3966cae..9abd4f1 100644
--- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h
+++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h
@@ -1,4 +1,4 @@
-//===-- MipsABIFlagsSection.h - Mips ELF ABI Flags Section -----*- C++ -*--===//
+//===- MipsABIFlagsSection.h - Mips ELF ABI Flags Section -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,9 +10,10 @@
#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIFLAGSSECTION_H
#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIFLAGSSECTION_H
-#include "llvm/MC/MCStreamer.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MipsABIFlags.h"
+#include <cstdint>
namespace llvm {
@@ -23,36 +24,32 @@ struct MipsABIFlagsSection {
enum class FpABIKind { ANY, XX, S32, S64, SOFT };
// Version of flags structure.
- uint16_t Version;
+ uint16_t Version = 0;
// The level of the ISA: 1-5, 32, 64.
- uint8_t ISALevel;
+ uint8_t ISALevel = 0;
// The revision of ISA: 0 for MIPS V and below, 1-n otherwise.
- uint8_t ISARevision;
+ uint8_t ISARevision = 0;
// The size of general purpose registers.
- Mips::AFL_REG GPRSize;
+ Mips::AFL_REG GPRSize = Mips::AFL_REG_NONE;
// The size of co-processor 1 registers.
- Mips::AFL_REG CPR1Size;
+ Mips::AFL_REG CPR1Size = Mips::AFL_REG_NONE;
// The size of co-processor 2 registers.
- Mips::AFL_REG CPR2Size;
+ Mips::AFL_REG CPR2Size = Mips::AFL_REG_NONE;
// Processor-specific extension.
- Mips::AFL_EXT ISAExtension;
+ Mips::AFL_EXT ISAExtension = Mips::AFL_EXT_NONE;
// Mask of ASEs used.
- uint32_t ASESet;
+ uint32_t ASESet = 0;
- bool OddSPReg;
+ bool OddSPReg = false;
- bool Is32BitABI;
+ bool Is32BitABI = false;
protected:
// The floating-point ABI.
- FpABIKind FpABI;
+ FpABIKind FpABI = FpABIKind::ANY;
public:
- MipsABIFlagsSection()
- : Version(0), ISALevel(0), ISARevision(0), GPRSize(Mips::AFL_REG_NONE),
- CPR1Size(Mips::AFL_REG_NONE), CPR2Size(Mips::AFL_REG_NONE),
- ISAExtension(Mips::AFL_EXT_NONE), ASESet(0), OddSPReg(false),
- Is32BitABI(false), FpABI(FpABIKind::ANY) {}
+ MipsABIFlagsSection() = default;
uint16_t getVersionValue() { return (uint16_t)Version; }
uint8_t getISALevelValue() { return (uint8_t)ISALevel; }
@@ -80,6 +77,7 @@ public:
FpABI = Value;
Is32BitABI = IsABI32Bit;
}
+
StringRef getFpABIString(FpABIKind Value);
template <class PredicateLibrary>
@@ -161,6 +159,8 @@ public:
ASESet |= Mips::AFL_ASE_MICROMIPS;
if (P.inMips16Mode())
ASESet |= Mips::AFL_ASE_MIPS16;
+ if (P.hasMT())
+ ASESet |= Mips::AFL_ASE_MT;
}
template <class PredicateLibrary>
@@ -195,6 +195,7 @@ public:
};
MCStreamer &operator<<(MCStreamer &OS, MipsABIFlagsSection &ABIFlagsSection);
-}
-#endif
+} // end namespace llvm
+
+#endif // LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIFLAGSSECTION_H
diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
index 38b11f7..a1ed0ea 100644
--- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
+++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
@@ -12,8 +12,8 @@
//===----------------------------------------------------------------------===//
//
-#include "MCTargetDesc/MipsFixupKinds.h"
#include "MCTargetDesc/MipsAsmBackend.h"
+#include "MCTargetDesc/MipsFixupKinds.h"
#include "MCTargetDesc/MipsMCExpr.h"
#include "MCTargetDesc/MipsMCTargetDesc.h"
#include "llvm/MC/MCAsmBackend.h"
@@ -34,7 +34,7 @@ using namespace llvm;
// Prepare value for the target space for it
static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
- MCContext *Ctx = nullptr) {
+ MCContext &Ctx) {
unsigned Kind = Fixup.getKind();
@@ -74,8 +74,8 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
// address range. Forcing a signed division because Value can be negative.
Value = (int64_t)Value / 4;
// We now check if Value can be encoded as a 16-bit signed immediate.
- if (!isInt<16>(Value) && Ctx) {
- Ctx->reportError(Fixup.getLoc(), "out of range PC16 fixup");
+ if (!isInt<16>(Value)) {
+ Ctx.reportError(Fixup.getLoc(), "out of range PC16 fixup");
return 0;
}
break;
@@ -84,8 +84,8 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
// Forcing a signed division because Value can be negative.
Value = (int64_t)Value / 4;
// We now check if Value can be encoded as a 19-bit signed immediate.
- if (!isInt<19>(Value) && Ctx) {
- Ctx->reportError(Fixup.getLoc(), "out of range PC19 fixup");
+ if (!isInt<19>(Value)) {
+ Ctx.reportError(Fixup.getLoc(), "out of range PC19 fixup");
return 0;
}
break;
@@ -121,8 +121,8 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
// Forcing a signed division because Value can be negative.
Value = (int64_t) Value / 2;
// We now check if Value can be encoded as a 7-bit signed immediate.
- if (!isInt<7>(Value) && Ctx) {
- Ctx->reportError(Fixup.getLoc(), "out of range PC7 fixup");
+ if (!isInt<7>(Value)) {
+ Ctx.reportError(Fixup.getLoc(), "out of range PC7 fixup");
return 0;
}
break;
@@ -131,8 +131,8 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
// Forcing a signed division because Value can be negative.
Value = (int64_t) Value / 2;
// We now check if Value can be encoded as a 10-bit signed immediate.
- if (!isInt<10>(Value) && Ctx) {
- Ctx->reportError(Fixup.getLoc(), "out of range PC10 fixup");
+ if (!isInt<10>(Value)) {
+ Ctx.reportError(Fixup.getLoc(), "out of range PC10 fixup");
return 0;
}
break;
@@ -141,8 +141,8 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
// Forcing a signed division because Value can be negative.
Value = (int64_t)Value / 2;
// We now check if Value can be encoded as a 16-bit signed immediate.
- if (!isInt<16>(Value) && Ctx) {
- Ctx->reportError(Fixup.getLoc(), "out of range PC16 fixup");
+ if (!isInt<16>(Value)) {
+ Ctx.reportError(Fixup.getLoc(), "out of range PC16 fixup");
return 0;
}
break;
@@ -150,21 +150,21 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
// Forcing a signed division because Value can be negative.
Value = (int64_t)Value / 8;
// We now check if Value can be encoded as a 18-bit signed immediate.
- if (!isInt<18>(Value) && Ctx) {
- Ctx->reportError(Fixup.getLoc(), "out of range PC18 fixup");
+ if (!isInt<18>(Value)) {
+ Ctx.reportError(Fixup.getLoc(), "out of range PC18 fixup");
return 0;
}
break;
case Mips::fixup_MICROMIPS_PC18_S3:
// Check alignment.
- if ((Value & 7) && Ctx) {
- Ctx->reportError(Fixup.getLoc(), "out of range PC18 fixup");
+ if ((Value & 7)) {
+ Ctx.reportError(Fixup.getLoc(), "out of range PC18 fixup");
}
// Forcing a signed division because Value can be negative.
Value = (int64_t)Value / 8;
// We now check if Value can be encoded as a 18-bit signed immediate.
- if (!isInt<18>(Value) && Ctx) {
- Ctx->reportError(Fixup.getLoc(), "out of range PC18 fixup");
+ if (!isInt<18>(Value)) {
+ Ctx.reportError(Fixup.getLoc(), "out of range PC18 fixup");
return 0;
}
break;
@@ -172,8 +172,8 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
// Forcing a signed division because Value can be negative.
Value = (int64_t) Value / 4;
// We now check if Value can be encoded as a 21-bit signed immediate.
- if (!isInt<21>(Value) && Ctx) {
- Ctx->reportError(Fixup.getLoc(), "out of range PC21 fixup");
+ if (!isInt<21>(Value)) {
+ Ctx.reportError(Fixup.getLoc(), "out of range PC21 fixup");
return 0;
}
break;
@@ -181,8 +181,8 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
// Forcing a signed division because Value can be negative.
Value = (int64_t) Value / 4;
// We now check if Value can be encoded as a 26-bit signed immediate.
- if (!isInt<26>(Value) && Ctx) {
- Ctx->reportError(Fixup.getLoc(), "out of range PC26 fixup");
+ if (!isInt<26>(Value)) {
+ Ctx.reportError(Fixup.getLoc(), "out of range PC26 fixup");
return 0;
}
break;
@@ -190,8 +190,8 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
// Forcing a signed division because Value can be negative.
Value = (int64_t)Value / 2;
// We now check if Value can be encoded as a 26-bit signed immediate.
- if (!isInt<26>(Value) && Ctx) {
- Ctx->reportFatalError(Fixup.getLoc(), "out of range PC26 fixup");
+ if (!isInt<26>(Value)) {
+ Ctx.reportFatalError(Fixup.getLoc(), "out of range PC26 fixup");
return 0;
}
break;
@@ -199,8 +199,8 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
// Forcing a signed division because Value can be negative.
Value = (int64_t)Value / 2;
// We now check if Value can be encoded as a 21-bit signed immediate.
- if (!isInt<21>(Value) && Ctx) {
- Ctx->reportError(Fixup.getLoc(), "out of range PC21 fixup");
+ if (!isInt<21>(Value)) {
+ Ctx.reportError(Fixup.getLoc(), "out of range PC21 fixup");
return 0;
}
break;
@@ -235,11 +235,13 @@ static unsigned calculateMMLEIndex(unsigned i) {
/// ApplyFixup - Apply the \p Value for given \p Fixup into the provided
/// data fragment, at the offset specified by the fixup and following the
/// fixup kind as appropriate.
-void MipsAsmBackend::applyFixup(const MCFixup &Fixup, char *Data,
- unsigned DataSize, uint64_t Value,
- bool IsPCRel) const {
+void MipsAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target,
+ MutableArrayRef<char> Data, uint64_t Value,
+ bool IsResolved) const {
MCFixupKind Kind = Fixup.getKind();
- Value = adjustFixupValue(Fixup, Value);
+ MCContext &Ctx = Asm.getContext();
+ Value = adjustFixupValue(Fixup, Value, Ctx);
if (!Value)
return; // Doesn't change encoding.
@@ -366,6 +368,7 @@ getFixupKindInfo(MCFixupKind Kind) const {
{ "fixup_MICROMIPS_TLS_LDM", 0, 16, 0 },
{ "fixup_MICROMIPS_TLS_DTPREL_HI16", 0, 16, 0 },
{ "fixup_MICROMIPS_TLS_DTPREL_LO16", 0, 16, 0 },
+ { "fixup_MICROMIPS_GOTTPREL", 0, 16, 0 },
{ "fixup_MICROMIPS_TLS_TPREL_HI16", 0, 16, 0 },
{ "fixup_MICROMIPS_TLS_TPREL_LO16", 0, 16, 0 },
{ "fixup_Mips_SUB", 0, 64, 0 },
@@ -437,6 +440,7 @@ getFixupKindInfo(MCFixupKind Kind) const {
{ "fixup_MICROMIPS_TLS_LDM", 16, 16, 0 },
{ "fixup_MICROMIPS_TLS_DTPREL_HI16", 16, 16, 0 },
{ "fixup_MICROMIPS_TLS_DTPREL_LO16", 16, 16, 0 },
+ { "fixup_MICROMIPS_GOTTPREL", 16, 16, 0 },
{ "fixup_MICROMIPS_TLS_TPREL_HI16", 16, 16, 0 },
{ "fixup_MICROMIPS_TLS_TPREL_LO16", 16, 16, 0 },
{ "fixup_Mips_SUB", 0, 64, 0 },
@@ -471,24 +475,6 @@ bool MipsAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const {
return true;
}
-/// processFixupValue - Target hook to process the literal value of a fixup
-/// if necessary.
-void MipsAsmBackend::processFixupValue(const MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCFixup &Fixup,
- const MCFragment *DF,
- const MCValue &Target,
- uint64_t &Value,
- bool &IsResolved) {
- // At this point we'll ignore the value returned by adjustFixupValue as
- // we are only checking if the fixup can be applied correctly. We have
- // access to MCContext from here which allows us to report a fatal error
- // with *possibly* a source code location.
- // The caller will also ignore any changes we make to Value
- // (recordRelocation() overwrites it with it's own calculation).
- (void)adjustFixupValue(Fixup, Value, &Asm.getContext());
-}
-
// MCAsmBackend
MCAsmBackend *llvm::createMipsAsmBackendEL32(const Target &T,
const MCRegisterInfo &MRI,
diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h
index f260cfa..8ebde3b 100644
--- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h
+++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h
@@ -38,8 +38,9 @@ public:
MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override;
- void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
- uint64_t Value, bool IsPCRel) const override;
+ void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target, MutableArrayRef<char> Data,
+ uint64_t Value, bool IsResolved) const override;
Optional<MCFixupKind> getFixupKind(StringRef Name) const override;
const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;
@@ -82,11 +83,6 @@ public:
bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
- void processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout,
- const MCFixup &Fixup, const MCFragment *DF,
- const MCValue &Target, uint64_t &Value,
- bool &IsResolved) override;
-
}; // class MipsAsmBackend
} // namespace
diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp
index b2efd72..d116ac3 100644
--- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp
+++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp
@@ -7,33 +7,38 @@
//
//===----------------------------------------------------------------------===//
-#include <algorithm>
-#include <list>
-#include "MCTargetDesc/MipsBaseInfo.h"
#include "MCTargetDesc/MipsFixupKinds.h"
-#include "MCTargetDesc/MipsMCExpr.h"
#include "MCTargetDesc/MipsMCTargetDesc.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/MC/MCAssembler.h"
+#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCELFObjectWriter.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCFixup.h"
#include "llvm/MC/MCSymbolELF.h"
-#include "llvm/MC/MCValue.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <iterator>
+#include <list>
+#include <utility>
#define DEBUG_TYPE "mips-elf-object-writer"
using namespace llvm;
namespace {
+
/// Holds additional information needed by the relocation ordering algorithm.
struct MipsRelocationEntry {
const ELFRelocationEntry R; ///< The relocation.
- bool Matched; ///< Is this relocation part of a match.
+ bool Matched = false; ///< Is this relocation part of a match.
- MipsRelocationEntry(const ELFRelocationEntry &R) : R(R), Matched(false) {}
+ MipsRelocationEntry(const ELFRelocationEntry &R) : R(R) {}
void print(raw_ostream &Out) const {
R.print(Out);
@@ -53,23 +58,33 @@ public:
MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, bool _isN64,
bool IsLittleEndian);
- ~MipsELFObjectWriter() override;
+ ~MipsELFObjectWriter() override = default;
unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
const MCFixup &Fixup, bool IsPCRel) const override;
bool needsRelocateWithSymbol(const MCSymbol &Sym,
unsigned Type) const override;
- virtual void sortRelocs(const MCAssembler &Asm,
- std::vector<ELFRelocationEntry> &Relocs) override;
+ void sortRelocs(const MCAssembler &Asm,
+ std::vector<ELFRelocationEntry> &Relocs) override;
+};
+
+/// The possible results of the Predicate function used by find_best.
+enum FindBestPredicateResult {
+ FindBest_NoMatch = 0, ///< The current element is not a match.
+ FindBest_Match, ///< The current element is a match but better ones are
+ /// possible.
+ FindBest_PerfectMatch, ///< The current element is an unbeatable match.
};
+} // end anonymous namespace
+
/// Copy elements in the range [First, Last) to d1 when the predicate is true or
/// d2 when the predicate is false. This is essentially both std::copy_if and
/// std::remove_copy_if combined into a single pass.
template <class InputIt, class OutputIt1, class OutputIt2, class UnaryPredicate>
-std::pair<OutputIt1, OutputIt2> copy_if_else(InputIt First, InputIt Last,
- OutputIt1 d1, OutputIt2 d2,
- UnaryPredicate Predicate) {
+static std::pair<OutputIt1, OutputIt2> copy_if_else(InputIt First, InputIt Last,
+ OutputIt1 d1, OutputIt2 d2,
+ UnaryPredicate Predicate) {
for (InputIt I = First; I != Last; ++I) {
if (Predicate(*I)) {
*d1 = *I;
@@ -83,14 +98,6 @@ std::pair<OutputIt1, OutputIt2> copy_if_else(InputIt First, InputIt Last,
return std::make_pair(d1, d2);
}
-/// The possible results of the Predicate function used by find_best.
-enum FindBestPredicateResult {
- FindBest_NoMatch = 0, ///< The current element is not a match.
- FindBest_Match, ///< The current element is a match but better ones are
- /// possible.
- FindBest_PerfectMatch, ///< The current element is an unbeatable match.
-};
-
/// Find the best match in the range [First, Last).
///
/// An element matches when Predicate(X) returns FindBest_Match or
@@ -101,8 +108,8 @@ enum FindBestPredicateResult {
/// This is similar to std::find_if but finds the best of multiple possible
/// matches.
template <class InputIt, class UnaryPredicate, class Comparator>
-InputIt find_best(InputIt First, InputIt Last, UnaryPredicate Predicate,
- Comparator BetterThan) {
+static InputIt find_best(InputIt First, InputIt Last, UnaryPredicate Predicate,
+ Comparator BetterThan) {
InputIt Best = Last;
for (InputIt I = First; I != Last; ++I) {
@@ -202,16 +209,12 @@ static void dumpRelocs(const char *Prefix, const Container &Relocs) {
}
#endif
-} // end anonymous namespace
-
MipsELFObjectWriter::MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI,
bool _isN64, bool IsLittleEndian)
: MCELFObjectTargetWriter(_is64Bit, OSABI, ELF::EM_MIPS,
/*HasRelocationAddend*/ _isN64,
/*IsN64*/ _isN64) {}
-MipsELFObjectWriter::~MipsELFObjectWriter() {}
-
unsigned MipsELFObjectWriter::getRelocType(MCContext &Ctx,
const MCValue &Target,
const MCFixup &Fixup,
@@ -371,6 +374,8 @@ unsigned MipsELFObjectWriter::getRelocType(MCContext &Ctx,
return ELF::R_MICROMIPS_TLS_DTPREL_HI16;
case Mips::fixup_MICROMIPS_TLS_DTPREL_LO16:
return ELF::R_MICROMIPS_TLS_DTPREL_LO16;
+ case Mips::fixup_MICROMIPS_GOTTPREL:
+ return ELF::R_MICROMIPS_TLS_GOTTPREL;
case Mips::fixup_MICROMIPS_TLS_TPREL_HI16:
return ELF::R_MICROMIPS_TLS_TPREL_HI16;
case Mips::fixup_MICROMIPS_TLS_TPREL_LO16:
@@ -419,7 +424,6 @@ unsigned MipsELFObjectWriter::getRelocType(MCContext &Ctx,
/// always match using the expressions from the source.
void MipsELFObjectWriter::sortRelocs(const MCAssembler &Asm,
std::vector<ELFRelocationEntry> &Relocs) {
-
// We do not need to sort the relocation table for RELA relocations which
// N32/N64 uses as the relocation addend contains the value we require,
// rather than it being split across a pair of relocations.
@@ -524,6 +528,8 @@ bool MipsELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym,
case ELF::R_MIPS_GOT16:
case ELF::R_MIPS16_GOT16:
case ELF::R_MICROMIPS_GOT16:
+ case ELF::R_MIPS_HIGHER:
+ case ELF::R_MIPS_HIGHEST:
case ELF::R_MIPS_HI16:
case ELF::R_MIPS16_HI16:
case ELF::R_MICROMIPS_HI16:
@@ -567,8 +573,6 @@ bool MipsELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym,
case ELF::R_MIPS_INSERT_A:
case ELF::R_MIPS_INSERT_B:
case ELF::R_MIPS_DELETE:
- case ELF::R_MIPS_HIGHER:
- case ELF::R_MIPS_HIGHEST:
case ELF::R_MIPS_CALL_HI16:
case ELF::R_MIPS_CALL_LO16:
case ELF::R_MIPS_SCN_DISP:
diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp
index e7d687e..f658aad 100644
--- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp
+++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp
@@ -8,15 +8,19 @@
//===----------------------------------------------------------------------===//
#include "MipsELFStreamer.h"
+#include "MipsOptionRecord.h"
#include "MipsTargetStreamer.h"
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCSymbolELF.h"
-#include "llvm/Support/ELF.h"
+#include "llvm/Support/Casting.h"
using namespace llvm;
void MipsELFStreamer::EmitInstruction(const MCInst &Inst,
- const MCSubtargetInfo &STI) {
+ const MCSubtargetInfo &STI, bool) {
MCELFStreamer::EmitInstruction(Inst, STI);
MCContext &Context = getContext();
@@ -51,7 +55,7 @@ void MipsELFStreamer::createPendingLabelRelocs() {
Labels.clear();
}
-void MipsELFStreamer::EmitLabel(MCSymbol *Symbol) {
+void MipsELFStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) {
MCELFStreamer::EmitLabel(Symbol);
Labels.push_back(Symbol);
}
diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h
index a241cde..f5eda11 100644
--- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h
+++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h
@@ -1,4 +1,4 @@
-//===-------- MipsELFStreamer.h - ELF Object Output -----------------------===//
+//===- MipsELFStreamer.h - ELF Object Output --------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -21,6 +21,7 @@
#include <memory>
namespace llvm {
+
class MCAsmBackend;
class MCCodeEmitter;
class MCContext;
@@ -31,12 +32,10 @@ class MipsELFStreamer : public MCELFStreamer {
MipsRegInfoRecord *RegInfoRecord;
SmallVector<MCSymbol*, 4> Labels;
-
public:
MipsELFStreamer(MCContext &Context, MCAsmBackend &MAB, raw_pwrite_stream &OS,
MCCodeEmitter *Emitter)
: MCELFStreamer(Context, MAB, OS, Emitter) {
-
RegInfoRecord = new MipsRegInfoRecord(this, Context);
MipsOptionRecords.push_back(
std::unique_ptr<MipsRegInfoRecord>(RegInfoRecord));
@@ -46,12 +45,13 @@ public:
/// \p Inst is actually emitted. For example, we can inspect the operands and
/// gather sufficient information that allows us to reason about the register
/// usage for the translation unit.
- void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override;
+ void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
+ bool = false) override;
/// Overriding this function allows us to record all labels that should be
/// marked as microMIPS. Based on this data marking is done in
/// EmitInstruction.
- void EmitLabel(MCSymbol *Symbol) override;
+ void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
/// Overriding this function allows us to dismiss all labels that are
/// candidates for marking as microMIPS when .section directive is processed.
@@ -72,5 +72,6 @@ public:
MCELFStreamer *createMipsELFStreamer(MCContext &Context, MCAsmBackend &MAB,
raw_pwrite_stream &OS,
MCCodeEmitter *Emitter, bool RelaxAll);
-} // namespace llvm.
-#endif
+} // end namespace llvm
+
+#endif // LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSELFSTREAMER_H
diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h
index 1492962..6148a1b 100644
--- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h
+++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h
@@ -203,6 +203,9 @@ namespace Mips {
// resulting in - R_MICROMIPS_TLS_DTPREL_LO16
fixup_MICROMIPS_TLS_DTPREL_LO16,
+ // resulting in - R_MICROMIPS_TLS_GOTTPREL.
+ fixup_MICROMIPS_GOTTPREL,
+
// resulting in - R_MICROMIPS_TLS_TPREL_HI16
fixup_MICROMIPS_TLS_TPREL_HI16,
diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp
index a44a35f..11411d9 100644
--- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp
+++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp
@@ -19,13 +19,11 @@ using namespace llvm;
void MipsMCAsmInfo::anchor() { }
MipsMCAsmInfo::MipsMCAsmInfo(const Triple &TheTriple) {
- if ((TheTriple.getArch() == Triple::mips) ||
- (TheTriple.getArch() == Triple::mips64))
- IsLittleEndian = false;
+ IsLittleEndian = TheTriple.isLittleEndian();
if ((TheTriple.getArch() == Triple::mips64el) ||
(TheTriple.getArch() == Triple::mips64)) {
- PointerSize = CalleeSaveStackSlotSize = 8;
+ CodePointerSize = CalleeSaveStackSlotSize = 8;
}
// FIXME: This condition isn't quite right but it's the best we can do until
diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
index 0614316..0330824 100644
--- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
+++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
@@ -10,22 +10,29 @@
// This file implements the MipsMCCodeEmitter class.
//
//===----------------------------------------------------------------------===//
-//
#include "MipsMCCodeEmitter.h"
#include "MCTargetDesc/MipsFixupKinds.h"
#include "MCTargetDesc/MipsMCExpr.h"
#include "MCTargetDesc/MipsMCTargetDesc.h"
#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/APInt.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCFixup.h"
#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <cstdint>
+
+using namespace llvm;
#define DEBUG_TYPE "mccodeemitter"
@@ -34,6 +41,7 @@
#undef GET_INSTRMAP_INFO
namespace llvm {
+
MCCodeEmitter *createMipsMCCodeEmitterEB(const MCInstrInfo &MCII,
const MCRegisterInfo &MRI,
MCContext &Ctx) {
@@ -45,12 +53,12 @@ MCCodeEmitter *createMipsMCCodeEmitterEL(const MCInstrInfo &MCII,
MCContext &Ctx) {
return new MipsMCCodeEmitter(MCII, Ctx, true);
}
-} // End of namespace llvm.
+
+} // end namespace llvm
// If the D<shift> instruction has a shift amount that is greater
// than 31 (checked in calling routine), lower it to a D<shift>32 instruction
static void LowerLargeShift(MCInst& Inst) {
-
assert(Inst.getNumOperands() == 3 && "Invalid no. of operands for shift!");
assert(Inst.getOperand(2).isImm());
@@ -103,24 +111,25 @@ static void LowerDins(MCInst& InstIn) {
assert(InstIn.getOperand(3).isImm());
int64_t size = InstIn.getOperand(3).getImm();
- if (size <= 32) {
- if (pos < 32) // DINS, do nothing
- return;
+ assert((pos + size) <= 64 &&
+ "DINS cannot have position plus size over 64");
+ if (pos < 32) {
+ if ((pos + size) > 0 && (pos + size) <= 32)
+ return; // DINS, do nothing
+ else if ((pos + size) > 32) {
+ //DINSM
+ InstIn.getOperand(3).setImm(size - 32);
+ InstIn.setOpcode(Mips::DINSM);
+ }
+ } else if ((pos + size) > 32 && (pos + size) <= 64) {
// DINSU
InstIn.getOperand(2).setImm(pos - 32);
InstIn.setOpcode(Mips::DINSU);
- return;
}
- // DINSM
- assert(pos < 32 && "DINS cannot have both size and pos > 32");
- InstIn.getOperand(3).setImm(size - 32);
- InstIn.setOpcode(Mips::DINSM);
- return;
}
// Fix a bad compact branch encoding for beqc/bnec.
void MipsMCCodeEmitter::LowerCompactBranch(MCInst& Inst) const {
-
// Encoding may be illegal !(rs < rt), but this situation is
// easily fixed.
unsigned RegOp0 = Inst.getOperand(0).getReg();
@@ -146,7 +155,6 @@ void MipsMCCodeEmitter::LowerCompactBranch(MCInst& Inst) const {
Inst.getOperand(0).setReg(RegOp1);
Inst.getOperand(1).setReg(RegOp0);
-
}
bool MipsMCCodeEmitter::isMicroMips(const MCSubtargetInfo &STI) const {
@@ -186,7 +194,6 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const
{
-
// Non-pseudo instructions that get changed for direct object
// only based on operand values.
// If this list of instructions get much longer we will move
@@ -272,7 +279,6 @@ unsigned MipsMCCodeEmitter::
getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
-
const MCOperand &MO = MI.getOperand(OpNo);
// If the destination is an immediate, divide by 4.
@@ -295,7 +301,6 @@ unsigned MipsMCCodeEmitter::
getBranchTargetOpValue1SImm16(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
-
const MCOperand &MO = MI.getOperand(OpNo);
// If the destination is an immediate, divide by 2.
@@ -318,7 +323,6 @@ unsigned MipsMCCodeEmitter::
getBranchTargetOpValueMMR6(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
-
const MCOperand &MO = MI.getOperand(OpNo);
// If the destination is an immediate, divide by 2.
@@ -342,7 +346,6 @@ unsigned MipsMCCodeEmitter::
getBranchTargetOpValueLsl2MMR6(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
-
const MCOperand &MO = MI.getOperand(OpNo);
// If the destination is an immediate, divide by 4.
@@ -366,7 +369,6 @@ unsigned MipsMCCodeEmitter::
getBranchTarget7OpValueMM(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
-
const MCOperand &MO = MI.getOperand(OpNo);
// If the destination is an immediate, divide by 2.
@@ -388,7 +390,6 @@ unsigned MipsMCCodeEmitter::
getBranchTargetOpValueMMPC10(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
-
const MCOperand &MO = MI.getOperand(OpNo);
// If the destination is an immediate, divide by 2.
@@ -410,7 +411,6 @@ unsigned MipsMCCodeEmitter::
getBranchTargetOpValueMM(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
-
const MCOperand &MO = MI.getOperand(OpNo);
// If the destination is an immediate, divide by 2.
@@ -433,7 +433,6 @@ unsigned MipsMCCodeEmitter::
getBranchTarget21OpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
-
const MCOperand &MO = MI.getOperand(OpNo);
// If the destination is an immediate, divide by 4.
@@ -456,7 +455,6 @@ unsigned MipsMCCodeEmitter::
getBranchTarget21OpValueMM(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
-
const MCOperand &MO = MI.getOperand(OpNo);
// If the destination is an immediate, divide by 4.
@@ -479,7 +477,6 @@ unsigned MipsMCCodeEmitter::
getBranchTarget26OpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
-
const MCOperand &MO = MI.getOperand(OpNo);
// If the destination is an immediate, divide by 4.
@@ -501,7 +498,6 @@ getBranchTarget26OpValue(const MCInst &MI, unsigned OpNo,
unsigned MipsMCCodeEmitter::getBranchTarget26OpValueMM(
const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
-
const MCOperand &MO = MI.getOperand(OpNo);
// If the destination is an immediate, divide by 2.
@@ -525,7 +521,6 @@ unsigned MipsMCCodeEmitter::
getJumpOffset16OpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
-
const MCOperand &MO = MI.getOperand(OpNo);
if (MO.isImm()) return MO.getImm();
@@ -544,7 +539,6 @@ unsigned MipsMCCodeEmitter::
getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
-
const MCOperand &MO = MI.getOperand(OpNo);
// If the destination is an immediate, divide by 4.
if (MO.isImm()) return MO.getImm()>>2;
@@ -562,7 +556,6 @@ unsigned MipsMCCodeEmitter::
getJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
-
const MCOperand &MO = MI.getOperand(OpNo);
// If the destination is an immediate, divide by 2.
if (MO.isImm()) return MO.getImm() >> 1;
@@ -580,7 +573,6 @@ unsigned MipsMCCodeEmitter::
getUImm5Lsl2Encoding(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
-
const MCOperand &MO = MI.getOperand(OpNo);
if (MO.isImm()) {
// The immediate is encoded as 'immediate << 2'.
@@ -599,7 +591,6 @@ unsigned MipsMCCodeEmitter::
getSImm3Lsa2Value(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
-
const MCOperand &MO = MI.getOperand(OpNo);
if (MO.isImm()) {
int Value = MO.getImm();
@@ -613,7 +604,6 @@ unsigned MipsMCCodeEmitter::
getUImm6Lsl2Encoding(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
-
const MCOperand &MO = MI.getOperand(OpNo);
if (MO.isImm()) {
unsigned Value = MO.getImm();
@@ -627,7 +617,6 @@ unsigned MipsMCCodeEmitter::
getSImm9AddiuspValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
-
const MCOperand &MO = MI.getOperand(OpNo);
if (MO.isImm()) {
unsigned Binary = (MO.getImm() >> 2) & 0x0000ffff;
@@ -680,7 +669,8 @@ getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups,
: Mips::fixup_Mips_DTPREL_LO;
break;
case MipsMCExpr::MEK_GOTTPREL:
- FixupKind = Mips::fixup_Mips_GOTTPREL;
+ FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOTTPREL
+ : Mips::fixup_Mips_GOTTPREL;
break;
case MipsMCExpr::MEK_GOT:
FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16
@@ -711,7 +701,7 @@ getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups,
case MipsMCExpr::MEK_GPREL:
FixupKind = Mips::fixup_Mips_GPREL16;
break;
- case MipsMCExpr::MEK_LO: {
+ case MipsMCExpr::MEK_LO:
// Check for %lo(%neg(%gp_rel(X)))
if (MipsExpr->isGpOff()) {
FixupKind = Mips::fixup_Mips_GPOFF_LO;
@@ -720,7 +710,6 @@ getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups,
FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16
: Mips::fixup_Mips_LO16;
break;
- }
case MipsMCExpr::MEK_HIGHEST:
FixupKind = Mips::fixup_Mips_HIGHEST;
break;
diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h
index 2d041dc..d12d319 100644
--- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h
+++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h
@@ -1,4 +1,4 @@
-//===-- MipsMCCodeEmitter.h - Convert Mips Code to Machine Code -----------===//
+//===- MipsMCCodeEmitter.h - Convert Mips Code to Machine Code --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,29 +10,25 @@
// This file defines the MipsMCCodeEmitter class.
//
//===----------------------------------------------------------------------===//
-//
#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCCODEEMITTER_H
#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCCODEEMITTER_H
#include "llvm/MC/MCCodeEmitter.h"
-#include "llvm/Support/DataTypes.h"
-
-using namespace llvm;
+#include <cstdint>
namespace llvm {
+
class MCContext;
class MCExpr;
+class MCFixup;
class MCInst;
class MCInstrInfo;
-class MCFixup;
class MCOperand;
class MCSubtargetInfo;
class raw_ostream;
class MipsMCCodeEmitter : public MCCodeEmitter {
- MipsMCCodeEmitter(const MipsMCCodeEmitter &) = delete;
- void operator=(const MipsMCCodeEmitter &) = delete;
const MCInstrInfo &MCII;
MCContext &Ctx;
bool IsLittleEndian;
@@ -43,8 +39,9 @@ class MipsMCCodeEmitter : public MCCodeEmitter {
public:
MipsMCCodeEmitter(const MCInstrInfo &mcii, MCContext &Ctx_, bool IsLittle)
: MCII(mcii), Ctx(Ctx_), IsLittleEndian(IsLittle) {}
-
- ~MipsMCCodeEmitter() override {}
+ MipsMCCodeEmitter(const MipsMCCodeEmitter &) = delete;
+ MipsMCCodeEmitter &operator=(const MipsMCCodeEmitter &) = delete;
+ ~MipsMCCodeEmitter() override = default;
void EmitByte(unsigned char C, raw_ostream &OS) const;
@@ -270,9 +267,11 @@ public:
unsigned getRegisterListOpValue16(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
- private:
+
+private:
void LowerCompactBranch(MCInst& Inst) const;
-}; // class MipsMCCodeEmitter
-} // namespace llvm.
+};
+
+} // end namespace llvm
-#endif
+#endif // LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCCODEEMITTER_H
diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp
index 082bb87..aad6bf3 100644
--- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp
+++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp
@@ -8,12 +8,18 @@
//===----------------------------------------------------------------------===//
#include "MipsMCExpr.h"
+#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCObjectStreamer.h"
+#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbolELF.h"
-#include "llvm/Support/ELF.h"
+#include "llvm/MC/MCValue.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdint>
using namespace llvm;
diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h
index d1a4334..495d525 100644
--- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h
+++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h
@@ -1,4 +1,4 @@
-//===-- MipsMCExpr.h - Mips specific MC expression classes ------*- C++ -*-===//
+//===- MipsMCExpr.h - Mips specific MC expression classes -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -70,6 +70,7 @@ public:
bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout,
const MCFixup *Fixup) const override;
void visitUsedExpr(MCStreamer &Streamer) const override;
+
MCFragment *findAssociatedFragment() const override {
return getSubExpr()->findAssociatedFragment();
}
@@ -86,6 +87,7 @@ public:
return isGpOff(Kind);
}
};
+
} // end namespace llvm
-#endif
+#endif // LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCEXPR_H
diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp
index aef9bd3..9266f0e 100644
--- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp
+++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp
@@ -20,7 +20,11 @@
#include "Mips.h"
#include "MipsELFStreamer.h"
#include "MipsMCNaCl.h"
+#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCELFStreamer.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cassert>
using namespace llvm;
@@ -38,14 +42,14 @@ class MipsNaClELFStreamer : public MipsELFStreamer {
public:
MipsNaClELFStreamer(MCContext &Context, MCAsmBackend &TAB,
raw_pwrite_stream &OS, MCCodeEmitter *Emitter)
- : MipsELFStreamer(Context, TAB, OS, Emitter), PendingCall(false) {}
+ : MipsELFStreamer(Context, TAB, OS, Emitter) {}
- ~MipsNaClELFStreamer() override {}
+ ~MipsNaClELFStreamer() override = default;
private:
// Whether we started the sandboxing sequence for calls. Calls are bundled
// with branch delays and aligned to the bundle end.
- bool PendingCall;
+ bool PendingCall = false;
bool isIndirectJump(const MCInst &MI) {
if (MI.getOpcode() == Mips::JALR) {
@@ -135,8 +139,8 @@ private:
public:
/// This function is the one used to emit instruction data into the ELF
/// streamer. We override it to mask dangerous instructions.
- void EmitInstruction(const MCInst &Inst,
- const MCSubtargetInfo &STI) override {
+ void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
+ bool) override {
// Sandbox indirect jumps.
if (isIndirectJump(Inst)) {
if (PendingCall)
@@ -265,4 +269,4 @@ MCELFStreamer *createMipsNaClELFStreamer(MCContext &Context, MCAsmBackend &TAB,
return S;
}
-}
+} // end namespace llvm
diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp
index 24b6028..2d84528 100644
--- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp
+++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp
@@ -1,4 +1,4 @@
-//===-- MipsOptionRecord.cpp - Abstraction for storing information --------===//
+//===- MipsOptionRecord.cpp - Abstraction for storing information ---------===//
//
// The LLVM Compiler Infrastructure
//
@@ -8,9 +8,15 @@
//===----------------------------------------------------------------------===//
#include "MipsOptionRecord.h"
+#include "MipsABIInfo.h"
#include "MipsELFStreamer.h"
#include "MipsTargetStreamer.h"
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSectionELF.h"
+#include <cassert>
using namespace llvm;
diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
index 7f79eb4..2907b77 100644
--- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
+++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
@@ -13,16 +13,17 @@
#include "MipsTargetStreamer.h"
#include "InstPrinter/MipsInstPrinter.h"
+#include "MCTargetDesc/MipsABIInfo.h"
#include "MipsELFStreamer.h"
#include "MipsMCExpr.h"
#include "MipsMCTargetDesc.h"
#include "MipsTargetObjectFile.h"
+#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbolELF.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/ELF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
@@ -49,6 +50,8 @@ void MipsTargetStreamer::emitDirectiveSetMacro() { forbidModuleDirective(); }
void MipsTargetStreamer::emitDirectiveSetNoMacro() { forbidModuleDirective(); }
void MipsTargetStreamer::emitDirectiveSetMsa() { forbidModuleDirective(); }
void MipsTargetStreamer::emitDirectiveSetNoMsa() { forbidModuleDirective(); }
+void MipsTargetStreamer::emitDirectiveSetMt() {}
+void MipsTargetStreamer::emitDirectiveSetNoMt() { forbidModuleDirective(); }
void MipsTargetStreamer::emitDirectiveSetAt() { forbidModuleDirective(); }
void MipsTargetStreamer::emitDirectiveSetAtWithArg(unsigned RegNo) {
forbidModuleDirective();
@@ -117,6 +120,7 @@ void MipsTargetStreamer::emitDirectiveModuleOddSPReg() {
}
void MipsTargetStreamer::emitDirectiveModuleSoftFloat() {}
void MipsTargetStreamer::emitDirectiveModuleHardFloat() {}
+void MipsTargetStreamer::emitDirectiveModuleMT() {}
void MipsTargetStreamer::emitDirectiveSetFp(
MipsABIFlagsSection::FpABIKind Value) {
forbidModuleDirective();
@@ -391,6 +395,16 @@ void MipsTargetAsmStreamer::emitDirectiveSetNoMsa() {
MipsTargetStreamer::emitDirectiveSetNoMsa();
}
+void MipsTargetAsmStreamer::emitDirectiveSetMt() {
+ OS << "\t.set\tmt\n";
+ MipsTargetStreamer::emitDirectiveSetMt();
+}
+
+void MipsTargetAsmStreamer::emitDirectiveSetNoMt() {
+ OS << "\t.set\tnomt\n";
+ MipsTargetStreamer::emitDirectiveSetNoMt();
+}
+
void MipsTargetAsmStreamer::emitDirectiveSetAt() {
OS << "\t.set\tat\n";
MipsTargetStreamer::emitDirectiveSetAt();
@@ -655,6 +669,10 @@ void MipsTargetAsmStreamer::emitDirectiveModuleHardFloat() {
OS << "\t.module\thardfloat\n";
}
+void MipsTargetAsmStreamer::emitDirectiveModuleMT() {
+ OS << "\t.module\tmt\n";
+}
+
// This part is for ELF object output.
MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S,
const MCSubtargetInfo &STI)
@@ -685,6 +703,17 @@ MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S,
// issues as well.
unsigned EFlags = MCA.getELFHeaderEFlags();
+ // FIXME: Fix a dependency issue by instantiating the ABI object to some
+ // default based off the triple. The triple doesn't describe the target
+ // fully, but any external user of the API that uses the MCTargetStreamer
+ // would otherwise crash on assertion failure.
+
+ ABI = MipsABIInfo(
+ STI.getTargetTriple().getArch() == Triple::ArchType::mipsel ||
+ STI.getTargetTriple().getArch() == Triple::ArchType::mips
+ ? MipsABIInfo::O32()
+ : MipsABIInfo::N64());
+
// Architecture
if (Features[Mips::FeatureMips64r6])
EFlags |= ELF::EF_MIPS_ARCH_64R6;
@@ -721,23 +750,18 @@ MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S,
if (Features[Mips::FeatureNaN2008])
EFlags |= ELF::EF_MIPS_NAN2008;
- // -mabicalls and -mplt are not implemented but we should act as if they were
- // given.
- EFlags |= ELF::EF_MIPS_CPIC;
-
MCA.setELFHeaderEFlags(EFlags);
}
void MipsTargetELFStreamer::emitLabel(MCSymbol *S) {
auto *Symbol = cast<MCSymbolELF>(S);
- if (!isMicroMipsEnabled())
- return;
getStreamer().getAssembler().registerSymbol(*Symbol);
uint8_t Type = Symbol->getType();
if (Type != ELF::STT_FUNC)
return;
- Symbol->setOther(ELF::STO_MIPS_MICROMIPS);
+ if (isMicroMipsEnabled())
+ Symbol->setOther(ELF::STO_MIPS_MICROMIPS);
}
void MipsTargetELFStreamer::finish() {
@@ -795,10 +819,13 @@ void MipsTargetELFStreamer::finish() {
} else if (Features[Mips::FeatureMips64r2] || Features[Mips::FeatureMips64])
EFlags |= ELF::EF_MIPS_32BITMODE;
- // If we've set the cpic eflag and we're n64, go ahead and set the pic
- // one as well.
- if (EFlags & ELF::EF_MIPS_CPIC && getABI().IsN64())
- EFlags |= ELF::EF_MIPS_PIC;
+ // -mplt is not implemented but we should act as if it was
+ // given.
+ if (!Features[Mips::FeatureNoABICalls])
+ EFlags |= ELF::EF_MIPS_CPIC;
+
+ if (Pic)
+ EFlags |= ELF::EF_MIPS_PIC | ELF::EF_MIPS_CPIC;
MCA.setELFHeaderEFlags(EFlags);
@@ -904,10 +931,10 @@ void MipsTargetELFStreamer::emitDirectiveEnd(StringRef Name) {
const MCExpr *Size = MCBinaryExpr::createSub(
MCSymbolRefExpr::create(CurPCSym, MCSymbolRefExpr::VK_None, Context),
ExprRef, Context);
- int64_t AbsSize;
- if (!Size->evaluateAsAbsolute(AbsSize, MCA))
- llvm_unreachable("Function size must be evaluatable as absolute");
- Size = MCConstantExpr::create(AbsSize, Context);
+
+ // The ELFObjectWriter can determine the absolute size as it has access to
+ // the layout information of the assembly file, so a size expression rather
+ // than an absolute value is ok here.
static_cast<MCSymbolELF *>(Sym)->setSize(Size);
}
diff --git a/contrib/llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td b/contrib/llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td
index 05aad51..38b09d1 100644
--- a/contrib/llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td
+++ b/contrib/llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td
@@ -475,29 +475,11 @@ defm : MaterializeImms<i64, ZERO_64, DADDIU_MM64R6, LUi64, ORi64>;
//
//===----------------------------------------------------------------------===//
-def : MipsPat<(MipsLo tglobaladdr:$in),
- (DADDIU_MM64R6 ZERO_64, tglobaladdr:$in)>, ISA_MICROMIPS64R6;
-def : MipsPat<(MipsLo tblockaddress:$in),
- (DADDIU_MM64R6 ZERO_64, tblockaddress:$in)>, ISA_MICROMIPS64R6;
-def : MipsPat<(MipsLo tjumptable:$in),
- (DADDIU_MM64R6 ZERO_64, tjumptable:$in)>, ISA_MICROMIPS64R6;
-def : MipsPat<(MipsLo tconstpool:$in),
- (DADDIU_MM64R6 ZERO_64, tconstpool:$in)>, ISA_MICROMIPS64R6;
-def : MipsPat<(MipsLo tglobaltlsaddr:$in),
- (DADDIU_MM64R6 ZERO_64, tglobaltlsaddr:$in)>, ISA_MICROMIPS64R6;
-def : MipsPat<(MipsLo texternalsym:$in),
- (DADDIU_MM64R6 ZERO_64, texternalsym:$in)>, ISA_MICROMIPS64R6;
-
-def : MipsPat<(add GPR64:$hi, (MipsLo tglobaladdr:$lo)),
- (DADDIU_MM64R6 GPR64:$hi, tglobaladdr:$lo)>, ISA_MICROMIPS64R6;
-def : MipsPat<(add GPR64:$hi, (MipsLo tblockaddress:$lo)),
- (DADDIU_MM64R6 GPR64:$hi, tblockaddress:$lo)>, ISA_MICROMIPS64R6;
-def : MipsPat<(add GPR64:$hi, (MipsLo tjumptable:$lo)),
- (DADDIU_MM64R6 GPR64:$hi, tjumptable:$lo)>, ISA_MICROMIPS64R6;
-def : MipsPat<(add GPR64:$hi, (MipsLo tconstpool:$lo)),
- (DADDIU_MM64R6 GPR64:$hi, tconstpool:$lo)>, ISA_MICROMIPS64R6;
-def : MipsPat<(add GPR64:$hi, (MipsLo tglobaltlsaddr:$lo)),
- (DADDIU_MM64R6 GPR64:$hi, tglobaltlsaddr:$lo)>, ISA_MICROMIPS64R6;
+defm : MipsHiLoRelocs<LUi64, DADDIU_MM64R6, ZERO_64, GPR64Opnd>, SYM_32,
+ ISA_MICROMIPS64R6;
+
+defm : MipsHighestHigherHiLoRelocs<LUi64, DADDIU_MM64R6>, SYM_64,
+ ISA_MICROMIPS64R6;
def : MipsPat<(addc GPR64:$lhs, GPR64:$rhs),
(DADDU_MM64R6 GPR64:$lhs, GPR64:$rhs)>, ISA_MICROMIPS64R6;
@@ -566,3 +548,15 @@ def : MipsInstAlias<"dnegu $rt, $rs",
def : MipsInstAlias<"dnegu $rt",
(DSUBU_MM64R6 GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rt), 1>,
ISA_MICROMIPS64R6;
+def : MipsInstAlias<"dsll $rd, $rt, $rs",
+ (DSLLV_MM64R6 GPR64Opnd:$rd, GPR64Opnd:$rt,
+ GPR32Opnd:$rs), 0>, ISA_MICROMIPS64R6;
+def : MipsInstAlias<"dsrl $rd, $rt, $rs",
+ (DSRLV_MM64R6 GPR64Opnd:$rd, GPR64Opnd:$rt,
+ GPR32Opnd:$rs), 0>, ISA_MICROMIPS64R6;
+def : MipsInstAlias<"dsrl $rd, $rt",
+ (DSRLV_MM64R6 GPR64Opnd:$rd, GPR64Opnd:$rd,
+ GPR32Opnd:$rt), 0>, ISA_MICROMIPS64R6;
+def : MipsInstAlias<"dsll $rd, $rt",
+ (DSLLV_MM64R6 GPR64Opnd:$rd, GPR64Opnd:$rd,
+ GPR32Opnd:$rt), 0>, ISA_MICROMIPS64R6;
diff --git a/contrib/llvm/lib/Target/Mips/MicroMipsInstrInfo.td b/contrib/llvm/lib/Target/Mips/MicroMipsInstrInfo.td
index c0de9e7..ee554bc 100644
--- a/contrib/llvm/lib/Target/Mips/MicroMipsInstrInfo.td
+++ b/contrib/llvm/lib/Target/Mips/MicroMipsInstrInfo.td
@@ -1136,12 +1136,6 @@ let Predicates = [InMicroMips] in {
def : MipsInstAlias<
"sgtu $rs, $rt",
(SLTu_MM GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>;
- def : MipsInstAlias<"slt $rs, $rt, $imm",
- (SLTi_MM GPR32Opnd:$rs, GPR32Opnd:$rt,
- simm32_relaxed:$imm), 0>;
- def : MipsInstAlias<"sltu $rs, $rt, $imm",
- (SLTiu_MM GPR32Opnd:$rs, GPR32Opnd:$rt,
- simm32_relaxed:$imm), 0>;
def : MipsInstAlias<"sll $rd, $rt, $rs",
(SLLV_MM GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>;
def : MipsInstAlias<"sra $rd, $rt, $rs",
@@ -1163,18 +1157,21 @@ let Predicates = [InMicroMips] in {
def : MipsInstAlias<"rotr $rt, $imm",
(ROTR_MM GPR32Opnd:$rt, GPR32Opnd:$rt, uimm5:$imm), 0>;
def : MipsInstAlias<"syscall", (SYSCALL_MM 0), 1>;
- def : MipsInstAlias<"and $rs, $rt, $imm",
- (ANDi_MM GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>;
- def : MipsInstAlias<"and $rs, $imm",
- (ANDi_MM GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm), 0>;
- def : MipsInstAlias<"or $rs, $rt, $imm",
- (ORi_MM GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>;
- def : MipsInstAlias<"or $rs, $imm",
- (ORi_MM GPR32Opnd:$rs, GPR32Opnd:$rs, uimm16:$imm), 0>;
- def : MipsInstAlias<"xor $rs, $rt, $imm",
- (XORi_MM GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>;
- def : MipsInstAlias<"xor $rs, $imm",
- (XORi_MM GPR32Opnd:$rs, GPR32Opnd:$rs, uimm16:$imm), 0>;
+
+ defm : OneOrTwoOperandMacroImmediateAlias<"add", ADDi_MM>;
+
+ defm : OneOrTwoOperandMacroImmediateAlias<"addu", ADDiu_MM>;
+
+ defm : OneOrTwoOperandMacroImmediateAlias<"and", ANDi_MM>;
+
+ defm : OneOrTwoOperandMacroImmediateAlias<"or", ORi_MM>;
+
+ defm : OneOrTwoOperandMacroImmediateAlias<"xor", XORi_MM>;
+
+ defm : OneOrTwoOperandMacroImmediateAlias<"slt", SLTi_MM>;
+
+ defm : OneOrTwoOperandMacroImmediateAlias<"sltu", SLTiu_MM>;
+
def : MipsInstAlias<"not $rt, $rs",
(NOR_MM GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>;
def : MipsInstAlias<"not $rt",
diff --git a/contrib/llvm/lib/Target/Mips/MicroMipsSizeReduction.cpp b/contrib/llvm/lib/Target/Mips/MicroMipsSizeReduction.cpp
new file mode 100644
index 0000000..35948e3
--- /dev/null
+++ b/contrib/llvm/lib/Target/Mips/MicroMipsSizeReduction.cpp
@@ -0,0 +1,392 @@
+//=== 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.
+//
+//===----------------------------------------------------------------------===//
+///\file
+/// This pass is used to reduce the size of instructions where applicable.
+///
+/// TODO: Implement microMIPS64 support.
+/// TODO: Implement support for reducing into lwp/swp instruction.
+//===----------------------------------------------------------------------===//
+#include "Mips.h"
+#include "MipsInstrInfo.h"
+#include "MipsSubtarget.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/Support/Debug.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "micromips-reduce-size"
+
+STATISTIC(NumReduced, "Number of 32-bit instructions reduced to 16-bit ones");
+
+namespace {
+
+/// Order of operands to transfer
+// TODO: Will be extended when additional optimizations are added
+enum OperandTransfer {
+ OT_NA, ///< Not applicable
+ OT_OperandsAll, ///< Transfer all operands
+};
+
+/// Reduction type
+// TODO: Will be extended when additional optimizations are added
+enum ReduceType {
+ RT_OneInstr ///< Reduce one instruction into a smaller instruction
+};
+
+// Information about immediate field restrictions
+struct ImmField {
+ ImmField() : ImmFieldOperand(-1), Shift(0), LBound(0), HBound(0) {}
+ ImmField(uint8_t Shift, int16_t LBound, int16_t HBound,
+ int8_t ImmFieldOperand)
+ : ImmFieldOperand(ImmFieldOperand), Shift(Shift), LBound(LBound),
+ HBound(HBound) {}
+ int8_t ImmFieldOperand; // Immediate operand, -1 if it does not exist
+ uint8_t Shift; // Shift value
+ int16_t LBound; // Low bound of the immediate operand
+ int16_t HBound; // High bound of the immediate operand
+};
+
+/// Information about operands
+// TODO: Will be extended when additional optimizations are added
+struct OpInfo {
+ OpInfo(enum OperandTransfer TransferOperands)
+ : TransferOperands(TransferOperands) {}
+ OpInfo() : TransferOperands(OT_NA) {}
+
+ enum OperandTransfer
+ TransferOperands; ///< Operands to transfer to the new instruction
+};
+
+// Information about opcodes
+struct OpCodes {
+ OpCodes(unsigned WideOpc, unsigned NarrowOpc)
+ : WideOpc(WideOpc), NarrowOpc(NarrowOpc) {}
+
+ unsigned WideOpc; ///< Wide opcode
+ unsigned NarrowOpc; ///< Narrow opcode
+};
+
+/// ReduceTable - A static table with information on mapping from wide
+/// opcodes to narrow
+struct ReduceEntry {
+
+ enum ReduceType eRType; ///< Reduction type
+ bool (*ReduceFunction)(
+ MachineInstr *MI,
+ const ReduceEntry &Entry); ///< Pointer to reduce function
+ struct OpCodes Ops; ///< All relevant OpCodes
+ struct OpInfo OpInf; ///< Characteristics of operands
+ struct ImmField Imm; ///< Characteristics of immediate field
+
+ ReduceEntry(enum ReduceType RType, struct OpCodes Op,
+ bool (*F)(MachineInstr *MI, const ReduceEntry &Entry),
+ struct OpInfo OpInf, struct ImmField Imm)
+ : eRType(RType), ReduceFunction(F), Ops(Op), OpInf(OpInf), Imm(Imm) {}
+
+ unsigned NarrowOpc() const { return Ops.NarrowOpc; }
+ unsigned WideOpc() const { return Ops.WideOpc; }
+ int16_t LBound() const { return Imm.LBound; }
+ int16_t HBound() const { return Imm.HBound; }
+ uint8_t Shift() const { return Imm.Shift; }
+ int8_t ImmField() const { return Imm.ImmFieldOperand; }
+ enum OperandTransfer TransferOperands() const {
+ return OpInf.TransferOperands;
+ }
+ enum ReduceType RType() const { return eRType; }
+
+ // operator used by std::equal_range
+ bool operator<(const unsigned int r) const { return (WideOpc() < r); }
+
+ // operator used by std::equal_range
+ friend bool operator<(const unsigned int r, const struct ReduceEntry &re) {
+ return (r < re.WideOpc());
+ }
+};
+
+class MicroMipsSizeReduce : public MachineFunctionPass {
+public:
+ static char ID;
+ MicroMipsSizeReduce();
+
+ static const MipsInstrInfo *MipsII;
+ const MipsSubtarget *Subtarget;
+
+ bool runOnMachineFunction(MachineFunction &MF) override;
+
+ llvm::StringRef getPassName() const override {
+ return "microMIPS instruction size reduction pass";
+ }
+
+private:
+ /// Reduces width of instructions in the specified basic block.
+ bool ReduceMBB(MachineBasicBlock &MBB);
+
+ /// Attempts to reduce MI, returns true on success.
+ bool ReduceMI(const MachineBasicBlock::instr_iterator &MII);
+
+ // Attempts to reduce LW/SW instruction into LWSP/SWSP,
+ // returns true on success.
+ static bool ReduceXWtoXWSP(MachineInstr *MI, const ReduceEntry &Entry);
+
+ // Attempts to reduce LBU/LHU instruction into LBU16/LHU16,
+ // returns true on success.
+ static bool ReduceLXUtoLXU16(MachineInstr *MI, const ReduceEntry &Entry);
+
+ // Attempts to reduce SB/SH instruction into SB16/SH16,
+ // returns true on success.
+ static bool ReduceSXtoSX16(MachineInstr *MI, const ReduceEntry &Entry);
+
+ // Attempts to reduce arithmetic instructions, returns true on success
+ static bool ReduceArithmeticInstructions(MachineInstr *MI,
+ const ReduceEntry &Entry);
+
+ // Changes opcode of an instruction
+ static bool ReplaceInstruction(MachineInstr *MI, const ReduceEntry &Entry);
+
+ // Table with transformation rules for each instruction
+ static llvm::SmallVector<ReduceEntry, 16> ReduceTable;
+};
+
+char MicroMipsSizeReduce::ID = 0;
+const MipsInstrInfo *MicroMipsSizeReduce::MipsII;
+
+// This table must be sorted by WideOpc as a main criterion and
+// ReduceType as a sub-criterion (when wide opcodes are the same)
+llvm::SmallVector<ReduceEntry, 16> MicroMipsSizeReduce::ReduceTable = {
+
+ // ReduceType, OpCodes, ReduceFunction,
+ // OpInfo(TransferOperands),
+ // ImmField(Shift, LBound, HBound, ImmFieldPosition)
+ {RT_OneInstr, OpCodes(Mips::ADDu, Mips::ADDU16_MM),
+ ReduceArithmeticInstructions, OpInfo(OT_OperandsAll),
+ ImmField(0, 0, 0, -1)},
+ {RT_OneInstr, OpCodes(Mips::ADDu_MM, Mips::ADDU16_MM),
+ ReduceArithmeticInstructions, OpInfo(OT_OperandsAll),
+ ImmField(0, 0, 0, -1)},
+ {RT_OneInstr, OpCodes(Mips::LBu, Mips::LBU16_MM), ReduceLXUtoLXU16,
+ OpInfo(OT_OperandsAll), ImmField(0, -1, 15, 2)},
+ {RT_OneInstr, OpCodes(Mips::LBu_MM, Mips::LBU16_MM), ReduceLXUtoLXU16,
+ OpInfo(OT_OperandsAll), ImmField(0, -1, 15, 2)},
+ {RT_OneInstr, OpCodes(Mips::LHu, Mips::LHU16_MM), ReduceLXUtoLXU16,
+ OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)},
+ {RT_OneInstr, OpCodes(Mips::LHu_MM, Mips::LHU16_MM), ReduceLXUtoLXU16,
+ OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)},
+ {RT_OneInstr, OpCodes(Mips::LW, Mips::LWSP_MM), ReduceXWtoXWSP,
+ OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)},
+ {RT_OneInstr, OpCodes(Mips::LW_MM, Mips::LWSP_MM), ReduceXWtoXWSP,
+ OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)},
+ {RT_OneInstr, OpCodes(Mips::SB, Mips::SB16_MM), ReduceSXtoSX16,
+ OpInfo(OT_OperandsAll), ImmField(0, 0, 16, 2)},
+ {RT_OneInstr, OpCodes(Mips::SB_MM, Mips::SB16_MM), ReduceSXtoSX16,
+ OpInfo(OT_OperandsAll), ImmField(0, 0, 16, 2)},
+ {RT_OneInstr, OpCodes(Mips::SH, Mips::SH16_MM), ReduceSXtoSX16,
+ OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)},
+ {RT_OneInstr, OpCodes(Mips::SH_MM, Mips::SH16_MM), ReduceSXtoSX16,
+ OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)},
+ {RT_OneInstr, OpCodes(Mips::SUBu, Mips::SUBU16_MM),
+ ReduceArithmeticInstructions, OpInfo(OT_OperandsAll),
+ ImmField(0, 0, 0, -1)},
+ {RT_OneInstr, OpCodes(Mips::SUBu_MM, Mips::SUBU16_MM),
+ ReduceArithmeticInstructions, OpInfo(OT_OperandsAll),
+ ImmField(0, 0, 0, -1)},
+ {RT_OneInstr, OpCodes(Mips::SW, Mips::SWSP_MM), ReduceXWtoXWSP,
+ OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)},
+ {RT_OneInstr, OpCodes(Mips::SW_MM, Mips::SWSP_MM), ReduceXWtoXWSP,
+ OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)},
+};
+}
+
+// Returns true if the machine operand MO is register SP
+static bool IsSP(const MachineOperand &MO) {
+ if (MO.isReg() && ((MO.getReg() == Mips::SP)))
+ return true;
+ return false;
+}
+
+// Returns true if the machine operand MO is register $16, $17, or $2-$7.
+static bool isMMThreeBitGPRegister(const MachineOperand &MO) {
+ if (MO.isReg() && Mips::GPRMM16RegClass.contains(MO.getReg()))
+ return true;
+ return false;
+}
+
+// Returns true if the machine operand MO is register $0, $17, or $2-$7.
+static bool isMMSourceRegister(const MachineOperand &MO) {
+ if (MO.isReg() && Mips::GPRMM16ZeroRegClass.contains(MO.getReg()))
+ return true;
+ return false;
+}
+
+// Returns true if the operand Op is an immediate value
+// and writes the immediate value into variable Imm
+static bool GetImm(MachineInstr *MI, unsigned Op, int64_t &Imm) {
+
+ if (!MI->getOperand(Op).isImm())
+ return false;
+ Imm = MI->getOperand(Op).getImm();
+ return true;
+}
+
+// Returns true if the variable Value has the number of least-significant zero
+// bits equal to Shift and if the shifted value is between the bounds
+static bool InRange(int64_t Value, unsigned short Shift, int LBound,
+ int HBound) {
+ int64_t Value2 = Value >> Shift;
+ if ((Value2 << Shift) == Value && (Value2 >= LBound) && (Value2 < HBound))
+ return true;
+ return false;
+}
+
+// Returns true if immediate operand is in range
+static bool ImmInRange(MachineInstr *MI, const ReduceEntry &Entry) {
+
+ int64_t offset;
+
+ if (!GetImm(MI, Entry.ImmField(), offset))
+ return false;
+
+ if (!InRange(offset, Entry.Shift(), Entry.LBound(), Entry.HBound()))
+ return false;
+
+ return true;
+}
+
+MicroMipsSizeReduce::MicroMipsSizeReduce() : MachineFunctionPass(ID) {}
+
+bool MicroMipsSizeReduce::ReduceMI(
+ const MachineBasicBlock::instr_iterator &MII) {
+
+ MachineInstr *MI = &*MII;
+ unsigned Opcode = MI->getOpcode();
+
+ // Search the table.
+ llvm::SmallVector<ReduceEntry, 16>::const_iterator Start =
+ std::begin(ReduceTable);
+ llvm::SmallVector<ReduceEntry, 16>::const_iterator End =
+ std::end(ReduceTable);
+
+ std::pair<llvm::SmallVector<ReduceEntry, 16>::const_iterator,
+ llvm::SmallVector<ReduceEntry, 16>::const_iterator>
+ Range = std::equal_range(Start, End, Opcode);
+
+ if (Range.first == Range.second)
+ return false;
+
+ for (llvm::SmallVector<ReduceEntry, 16>::const_iterator Entry = Range.first;
+ Entry != Range.second; ++Entry)
+ if (((*Entry).ReduceFunction)(&(*MII), *Entry))
+ return true;
+
+ return false;
+}
+
+bool MicroMipsSizeReduce::ReduceXWtoXWSP(MachineInstr *MI,
+ const ReduceEntry &Entry) {
+
+ if (!ImmInRange(MI, Entry))
+ return false;
+
+ if (!IsSP(MI->getOperand(1)))
+ return false;
+
+ return ReplaceInstruction(MI, Entry);
+}
+
+bool MicroMipsSizeReduce::ReduceArithmeticInstructions(
+ MachineInstr *MI, const ReduceEntry &Entry) {
+
+ if (!isMMThreeBitGPRegister(MI->getOperand(0)) ||
+ !isMMThreeBitGPRegister(MI->getOperand(1)) ||
+ !isMMThreeBitGPRegister(MI->getOperand(2)))
+ return false;
+
+ return ReplaceInstruction(MI, Entry);
+}
+
+bool MicroMipsSizeReduce::ReduceLXUtoLXU16(MachineInstr *MI,
+ const ReduceEntry &Entry) {
+
+ if (!ImmInRange(MI, Entry))
+ return false;
+
+ if (!isMMThreeBitGPRegister(MI->getOperand(0)) ||
+ !isMMThreeBitGPRegister(MI->getOperand(1)))
+ return false;
+
+ return ReplaceInstruction(MI, Entry);
+}
+
+bool MicroMipsSizeReduce::ReduceSXtoSX16(MachineInstr *MI,
+ const ReduceEntry &Entry) {
+
+ if (!ImmInRange(MI, Entry))
+ return false;
+
+ if (!isMMSourceRegister(MI->getOperand(0)) ||
+ !isMMThreeBitGPRegister(MI->getOperand(1)))
+ return false;
+
+ return ReplaceInstruction(MI, Entry);
+}
+
+bool MicroMipsSizeReduce::ReduceMBB(MachineBasicBlock &MBB) {
+ bool Modified = false;
+ MachineBasicBlock::instr_iterator MII = MBB.instr_begin(),
+ E = MBB.instr_end();
+ MachineBasicBlock::instr_iterator NextMII;
+
+ // Iterate through the instructions in the basic block
+ for (; MII != E; MII = NextMII) {
+ NextMII = std::next(MII);
+ MachineInstr *MI = &*MII;
+
+ // Don't reduce bundled instructions or pseudo operations
+ if (MI->isBundle() || MI->isTransient())
+ continue;
+
+ // Try to reduce 32-bit instruction into 16-bit instruction
+ Modified |= ReduceMI(MII);
+ }
+
+ return Modified;
+}
+
+bool MicroMipsSizeReduce::ReplaceInstruction(MachineInstr *MI,
+ const ReduceEntry &Entry) {
+
+ MI->setDesc(MipsII->get(Entry.NarrowOpc()));
+ DEBUG(dbgs() << "Converted into 16-bit: " << *MI);
+ ++NumReduced;
+ return true;
+}
+
+bool MicroMipsSizeReduce::runOnMachineFunction(MachineFunction &MF) {
+
+ Subtarget = &static_cast<const MipsSubtarget &>(MF.getSubtarget());
+
+ // TODO: Add support for other subtargets:
+ // microMIPS32r6 and microMIPS64r6
+ if (!Subtarget->inMicroMipsMode() || !Subtarget->hasMips32r2())
+ return false;
+
+ MipsII = static_cast<const MipsInstrInfo *>(Subtarget->getInstrInfo());
+
+ bool Modified = false;
+ MachineFunction::iterator I = MF.begin(), E = MF.end();
+
+ for (; I != E; ++I)
+ Modified |= ReduceMBB(*I);
+ return Modified;
+}
+
+/// Returns an instance of the MicroMips size reduction pass.
+FunctionPass *llvm::createMicroMipsSizeReductionPass() {
+ return new MicroMipsSizeReduce();
+}
diff --git a/contrib/llvm/lib/Target/Mips/Mips.h b/contrib/llvm/lib/Target/Mips/Mips.h
index d9faf33..008b950 100644
--- a/contrib/llvm/lib/Target/Mips/Mips.h
+++ b/contrib/llvm/lib/Target/Mips/Mips.h
@@ -23,15 +23,16 @@ namespace llvm {
class ModulePass;
class FunctionPass;
- ModulePass *createMipsOs16Pass(MipsTargetMachine &TM);
- ModulePass *createMips16HardFloatPass(MipsTargetMachine &TM);
+ ModulePass *createMipsOs16Pass();
+ ModulePass *createMips16HardFloatPass();
- FunctionPass *createMipsModuleISelDagPass(MipsTargetMachine &TM);
- FunctionPass *createMipsOptimizePICCallPass(MipsTargetMachine &TM);
- FunctionPass *createMipsDelaySlotFillerPass(MipsTargetMachine &TM);
+ FunctionPass *createMipsModuleISelDagPass();
+ FunctionPass *createMipsOptimizePICCallPass();
+ FunctionPass *createMipsDelaySlotFillerPass();
FunctionPass *createMipsHazardSchedule();
- FunctionPass *createMipsLongBranchPass(MipsTargetMachine &TM);
+ FunctionPass *createMipsLongBranchPass();
FunctionPass *createMipsConstantIslandPass();
+ FunctionPass *createMicroMipsSizeReductionPass();
} // end namespace llvm;
#endif
diff --git a/contrib/llvm/lib/Target/Mips/Mips.td b/contrib/llvm/lib/Target/Mips/Mips.td
index 670272d..6ceb055 100644
--- a/contrib/llvm/lib/Target/Mips/Mips.td
+++ b/contrib/llvm/lib/Target/Mips/Mips.td
@@ -156,6 +156,8 @@ def FeatureMips64r6 : SubtargetFeature<"mips64r6", "MipsArchVersion",
"Mips64r6 ISA Support [experimental]",
[FeatureMips32r6, FeatureMips64r5,
FeatureNaN2008]>;
+def FeatureSym32 : SubtargetFeature<"sym32", "HasSym32", "true",
+ "Symbols are 32 bit on Mips64">;
def FeatureMips16 : SubtargetFeature<"mips16", "InMips16Mode", "true",
"Mips16 mode">;
@@ -183,6 +185,14 @@ def FeatureUseTCCInDIV : SubtargetFeature<
"UseTCCInDIV", "false",
"Force the assembler to use trapping">;
+def FeatureMadd4 : SubtargetFeature<"nomadd4", "DisableMadd4", "true",
+ "Disable 4-operand madd.fmt and related instructions">;
+
+def FeatureMT : SubtargetFeature<"mt", "HasMT", "true", "Mips MT ASE">;
+
+def FeatureLongCalls : SubtargetFeature<"long-calls", "UseLongCalls", "true",
+ "Disable use of the jal instruction">;
+
//===----------------------------------------------------------------------===//
// Mips processors supported.
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/lib/Target/Mips/Mips16FrameLowering.cpp b/contrib/llvm/lib/Target/Mips/Mips16FrameLowering.cpp
index e7ceca9..09e41e1 100644
--- a/contrib/llvm/lib/Target/Mips/Mips16FrameLowering.cpp
+++ b/contrib/llvm/lib/Target/Mips/Mips16FrameLowering.cpp
@@ -1,4 +1,4 @@
-//===-- Mips16FrameLowering.cpp - Mips16 Frame Information ----------------===//
+//===- Mips16FrameLowering.cpp - Mips16 Frame Information -----------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,14 +17,23 @@
#include "MipsInstrInfo.h"
#include "MipsRegisterInfo.h"
#include "MipsSubtarget.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
-#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/IR/DataLayout.h"
-#include "llvm/IR/Function.h"
-#include "llvm/Target/TargetOptions.h"
+#include "llvm/IR/DebugLoc.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDwarf.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MachineLocation.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Target/TargetFrameLowering.h"
+#include <cassert>
+#include <cstdint>
+#include <vector>
using namespace llvm;
@@ -63,7 +72,7 @@ void Mips16FrameLowering::emitPrologue(MachineFunction &MF,
const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
- if (CSI.size()) {
+ if (!CSI.empty()) {
const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(),
@@ -80,7 +89,6 @@ void Mips16FrameLowering::emitPrologue(MachineFunction &MF,
if (hasFP(MF))
BuildMI(MBB, MBBI, dl, TII.get(Mips::MoveR3216), Mips::S0)
.addReg(Mips::SP).setMIFlag(MachineInstr::FrameSetup);
-
}
void Mips16FrameLowering::emitEpilogue(MachineFunction &MF,
diff --git a/contrib/llvm/lib/Target/Mips/Mips16HardFloat.cpp b/contrib/llvm/lib/Target/Mips/Mips16HardFloat.cpp
index 191006d..3c24261 100644
--- a/contrib/llvm/lib/Target/Mips/Mips16HardFloat.cpp
+++ b/contrib/llvm/lib/Target/Mips/Mips16HardFloat.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "MipsTargetMachine.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/Debug.h"
@@ -28,14 +29,16 @@ namespace {
public:
static char ID;
- Mips16HardFloat(MipsTargetMachine &TM_) : ModulePass(ID), TM(TM_) {}
+ Mips16HardFloat() : ModulePass(ID) {}
StringRef getPassName() const override { return "MIPS16 Hard Float Pass"; }
- bool runOnModule(Module &M) override;
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addRequired<TargetPassConfig>();
+ ModulePass::getAnalysisUsage(AU);
+ }
- protected:
- const MipsTargetMachine &TM;
+ bool runOnModule(Module &M) override;
};
static void EmitInlineAsm(LLVMContext &C, BasicBlock *BB, StringRef AsmText) {
@@ -405,7 +408,7 @@ static bool fixupFPReturnAndCall(Function &F, Module *M,
"__mips16_ret_dc"
};
const char *Name = Helper[RV];
- AttributeSet A;
+ AttributeList A;
Value *Params[] = {RVal};
Modified = true;
//
@@ -414,13 +417,13 @@ static bool fixupFPReturnAndCall(Function &F, Module *M,
// during call setup, the proper call lowering to the helper
// functions will take place.
//
- A = A.addAttribute(C, AttributeSet::FunctionIndex,
+ A = A.addAttribute(C, AttributeList::FunctionIndex,
"__Mips16RetHelper");
- A = A.addAttribute(C, AttributeSet::FunctionIndex,
+ A = A.addAttribute(C, AttributeList::FunctionIndex,
Attribute::ReadNone);
- A = A.addAttribute(C, AttributeSet::FunctionIndex,
+ A = A.addAttribute(C, AttributeList::FunctionIndex,
Attribute::NoInline);
- Value *F = (M->getOrInsertFunction(Name, A, MyVoid, T, nullptr));
+ Value *F = (M->getOrInsertFunction(Name, A, MyVoid, T));
CallInst::Create(F, Params, "", &I);
} else if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
FunctionType *FT = CI->getFunctionType();
@@ -490,15 +493,14 @@ static void createFPFnStub(Function *F, Module *M, FPParamVariant PV,
// remove the use-soft-float attribute
//
static void removeUseSoftFloat(Function &F) {
- AttributeSet A;
+ AttrBuilder B;
DEBUG(errs() << "removing -use-soft-float\n");
- A = A.addAttribute(F.getContext(), AttributeSet::FunctionIndex,
- "use-soft-float", "false");
- F.removeAttributes(AttributeSet::FunctionIndex, A);
+ B.addAttribute("use-soft-float", "false");
+ F.removeAttributes(AttributeList::FunctionIndex, B);
if (F.hasFnAttribute("use-soft-float")) {
DEBUG(errs() << "still has -use-soft-float\n");
}
- F.addAttributes(AttributeSet::FunctionIndex, A);
+ F.addAttributes(AttributeList::FunctionIndex, B);
}
@@ -521,6 +523,8 @@ static void removeUseSoftFloat(Function &F) {
// during call lowering but it should be moved here in the future.
//
bool Mips16HardFloat::runOnModule(Module &M) {
+ auto &TM = static_cast<const MipsTargetMachine &>(
+ getAnalysis<TargetPassConfig>().getTM<TargetMachine>());
DEBUG(errs() << "Run on Module Mips16HardFloat\n");
bool Modified = false;
for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
@@ -542,6 +546,6 @@ bool Mips16HardFloat::runOnModule(Module &M) {
}
-ModulePass *llvm::createMips16HardFloatPass(MipsTargetMachine &TM) {
- return new Mips16HardFloat(TM);
+ModulePass *llvm::createMips16HardFloatPass() {
+ return new Mips16HardFloat();
}
diff --git a/contrib/llvm/lib/Target/Mips/Mips16InstrInfo.td b/contrib/llvm/lib/Target/Mips/Mips16InstrInfo.td
index 021fb86..52bf690 100644
--- a/contrib/llvm/lib/Target/Mips/Mips16InstrInfo.td
+++ b/contrib/llvm/lib/Target/Mips/Mips16InstrInfo.td
@@ -766,6 +766,7 @@ def JrRa16: FRR16_JALRC_RA_only_ins<0, 0, "jr", IIM16Alu> {
let hasDelaySlot = 1;
let isTerminator=1;
let isBarrier=1;
+ let isReturn=1;
}
def JrcRa16: FRR16_JALRC_RA_only_ins<1, 1, "jrc", IIM16Alu> {
@@ -773,6 +774,7 @@ def JrcRa16: FRR16_JALRC_RA_only_ins<1, 1, "jrc", IIM16Alu> {
let isIndirectBranch = 1;
let isTerminator=1;
let isBarrier=1;
+ let isReturn=1;
}
def JrcRx16: FRR16_JALRC_ins<1, 1, 0, "jrc", IIM16Alu> {
diff --git a/contrib/llvm/lib/Target/Mips/Mips32r6InstrInfo.td b/contrib/llvm/lib/Target/Mips/Mips32r6InstrInfo.td
index 1b4d73b..7daea16 100644
--- a/contrib/llvm/lib/Target/Mips/Mips32r6InstrInfo.td
+++ b/contrib/llvm/lib/Target/Mips/Mips32r6InstrInfo.td
@@ -326,9 +326,9 @@ class AUIPC_DESC : ALUIPC_DESC_BASE<"auipc", GPR32Opnd, II_AUIPC>;
class AUI_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,
InstrItinClass itin = NoItinerary>
: MipsR6Arch<instr_asm> {
- dag OutOperandList = (outs GPROpnd:$rs);
- dag InOperandList = (ins GPROpnd:$rt, uimm16:$imm);
- string AsmString = !strconcat(instr_asm, "\t$rs, $rt, $imm");
+ dag OutOperandList = (outs GPROpnd:$rt);
+ dag InOperandList = (ins GPROpnd:$rs, uimm16:$imm);
+ string AsmString = !strconcat(instr_asm, "\t$rt, $rs, $imm");
list<dag> Pattern = [];
InstrItinClass Itinerary = itin;
}
@@ -917,6 +917,12 @@ def : MipsInstAlias<"jrc $rs", (JIC GPR32Opnd:$rs, 0), 1>, ISA_MIPS32R6, GPR_32;
let AdditionalPredicates = [NotInMicroMips] in {
def : MipsInstAlias<"jalrc $rs", (JIALC GPR32Opnd:$rs, 0), 1>, ISA_MIPS32R6, GPR_32;
}
+
+def : MipsInstAlias<"div $rs, $rt", (DIV GPR32Opnd:$rs, GPR32Opnd:$rs,
+ GPR32Opnd:$rt)>, ISA_MIPS32R6;
+def : MipsInstAlias<"divu $rs, $rt", (DIVU GPR32Opnd:$rs, GPR32Opnd:$rs,
+ GPR32Opnd:$rt)>, ISA_MIPS32R6;
+
//===----------------------------------------------------------------------===//
//
// Patterns and Pseudo Instructions
diff --git a/contrib/llvm/lib/Target/Mips/Mips64InstrInfo.td b/contrib/llvm/lib/Target/Mips/Mips64InstrInfo.td
index 521e22f..3dba7ce 100644
--- a/contrib/llvm/lib/Target/Mips/Mips64InstrInfo.td
+++ b/contrib/llvm/lib/Target/Mips/Mips64InstrInfo.td
@@ -326,6 +326,14 @@ let AdditionalPredicates = [NotInMicroMips] in {
EXT_FM<5>, ISA_MIPS64R2;
}
+let isCodeGenOnly = 1, AdditionalPredicates = [NotInMicroMips] in {
+ def DEXT64_32 : InstSE<(outs GPR64Opnd:$rt),
+ (ins GPR32Opnd:$rs, uimm5_report_uimm6:$pos,
+ uimm5_plus1:$size),
+ "dext $rt, $rs, $pos, $size", [], II_EXT, FrmR, "dext">,
+ EXT_FM<3>, ISA_MIPS64R2;
+}
+
let isCodeGenOnly = 1, rs = 0, shamt = 0 in {
def DSLL64_32 : FR<0x00, 0x3c, (outs GPR64:$rd), (ins GPR32:$rt),
"dsll\t$rd, $rt, 32", [], II_DSLL>;
@@ -356,11 +364,11 @@ class Count1s<string opstr, RegisterOperand RO>:
let TwoOperandAliasConstraint = "$rd = $rs";
}
-class ExtsCins<string opstr, InstrItinClass itin,
- SDPatternOperator Op = null_frag>:
- InstSE<(outs GPR64Opnd:$rt), (ins GPR64Opnd:$rs, uimm5:$pos, uimm5:$lenm1),
- !strconcat(opstr, " $rt, $rs, $pos, $lenm1"),
- [(set GPR64Opnd:$rt, (Op GPR64Opnd:$rs, imm:$pos, imm:$lenm1))],
+class ExtsCins<string opstr, InstrItinClass itin, RegisterOperand RO,
+ PatFrag PosImm, SDPatternOperator Op = null_frag>:
+ InstSE<(outs RO:$rt), (ins RO:$rs, uimm5:$pos, uimm5:$lenm1),
+ !strconcat(opstr, "\t$rt, $rs, $pos, $lenm1"),
+ [(set RO:$rt, (Op RO:$rs, PosImm:$pos, imm:$lenm1))],
itin, FrmR, opstr> {
let TwoOperandAliasConstraint = "$rt = $rs";
}
@@ -424,13 +432,28 @@ def DMUL : ArithLogicR<"dmul", GPR64Opnd, 1, II_DMUL, mul>,
let Defs = [HI0, LO0, P0, P1, P2];
}
-// Extract a signed bit field /+32
-def EXTS : ExtsCins<"exts", II_EXT>, EXTS_FM<0x3a>, ASE_CNMIPS;
-def EXTS32: ExtsCins<"exts32", II_EXT>, EXTS_FM<0x3b>, ASE_CNMIPS;
-
-// Clear and insert a bit field /+32
-def CINS : ExtsCins<"cins", II_INS>, EXTS_FM<0x32>, ASE_CNMIPS;
-def CINS32: ExtsCins<"cins32", II_INS>, EXTS_FM<0x33>, ASE_CNMIPS;
+let AdditionalPredicates = [NotInMicroMips] in {
+ // Extract a signed bit field /+32
+ def EXTS : ExtsCins<"exts", II_EXT, GPR64Opnd, immZExt5>, EXTS_FM<0x3a>,
+ ASE_MIPS64_CNMIPS;
+ def EXTS32: ExtsCins<"exts32", II_EXT, GPR64Opnd, immZExt5Plus32>,
+ EXTS_FM<0x3b>, ASE_MIPS64_CNMIPS;
+
+ // Clear and insert a bit field /+32
+ def CINS : ExtsCins<"cins", II_INS, GPR64Opnd, immZExt5, MipsCIns>,
+ EXTS_FM<0x32>, ASE_MIPS64_CNMIPS;
+ def CINS32: ExtsCins<"cins32", II_INS, GPR64Opnd, immZExt5Plus32, MipsCIns>,
+ EXTS_FM<0x33>, ASE_MIPS64_CNMIPS;
+ let isCodeGenOnly = 1 in {
+ def CINS_i32 : ExtsCins<"cins", II_INS, GPR32Opnd, immZExt5, MipsCIns>,
+ EXTS_FM<0x32>, ASE_MIPS64_CNMIPS;
+ def CINS64_32 :InstSE<(outs GPR64Opnd:$rt),
+ (ins GPR32Opnd:$rs, uimm5:$pos, uimm5:$lenm1),
+ "cins\t$rt, $rs, $pos, $lenm1", [], II_INS, FrmR,
+ "cins">,
+ EXTS_FM<0x32>, ASE_MIPS64_CNMIPS;
+ }
+}
// Move to multiplier/product register
def MTM0 : MoveToLOHI<"mtm0", GPR64Opnd, [MPL0, P0, P1, P2]>, MTMR_FM<0x08>,
@@ -513,41 +536,87 @@ def : MipsPat<(i64 (extloadi16 addr:$src)), (LH64 addr:$src)>;
def : MipsPat<(i64 (extloadi32 addr:$src)), (LW64 addr:$src)>;
// hi/lo relocs
-def : MipsPat<(MipsHi tglobaladdr:$in), (LUi64 tglobaladdr:$in)>;
-def : MipsPat<(MipsHi tblockaddress:$in), (LUi64 tblockaddress:$in)>;
-def : MipsPat<(MipsHi tjumptable:$in), (LUi64 tjumptable:$in)>;
-def : MipsPat<(MipsHi tconstpool:$in), (LUi64 tconstpool:$in)>;
-def : MipsPat<(MipsHi tglobaltlsaddr:$in), (LUi64 tglobaltlsaddr:$in)>;
-def : MipsPat<(MipsHi texternalsym:$in), (LUi64 texternalsym:$in)>;
+let AdditionalPredicates = [NotInMicroMips] in
+defm : MipsHiLoRelocs<LUi64, DADDiu, ZERO_64, GPR64Opnd>, SYM_32;
+
+def : MipsPat<(MipsGotHi tglobaladdr:$in), (LUi64 tglobaladdr:$in)>;
+def : MipsPat<(MipsGotHi texternalsym:$in), (LUi64 texternalsym:$in)>;
+
+multiclass MipsHighestHigherHiLoRelocs<Instruction Lui, Instruction Daddiu> {
+ def : MipsPat<(MipsJmpLink (i64 texternalsym:$dst)),
+ (JAL texternalsym:$dst)>;
+ def : MipsPat<(MipsHighest (i64 tglobaladdr:$in)),
+ (Lui tglobaladdr:$in)>;
+ def : MipsPat<(MipsHighest (i64 tblockaddress:$in)),
+ (Lui tblockaddress:$in)>;
+ def : MipsPat<(MipsHighest (i64 tjumptable:$in)),
+ (Lui tjumptable:$in)>;
+ def : MipsPat<(MipsHighest (i64 tconstpool:$in)),
+ (Lui tconstpool:$in)>;
+ def : MipsPat<(MipsHighest (i64 tglobaltlsaddr:$in)),
+ (Lui tglobaltlsaddr:$in)>;
+ def : MipsPat<(MipsHighest (i64 texternalsym:$in)),
+ (Lui texternalsym:$in)>;
+
+ def : MipsPat<(MipsHigher (i64 tglobaladdr:$in)),
+ (Daddiu ZERO_64, tglobaladdr:$in)>;
+ def : MipsPat<(MipsHigher (i64 tblockaddress:$in)),
+ (Daddiu ZERO_64, tblockaddress:$in)>;
+ def : MipsPat<(MipsHigher (i64 tjumptable:$in)),
+ (Daddiu ZERO_64, tjumptable:$in)>;
+ def : MipsPat<(MipsHigher (i64 tconstpool:$in)),
+ (Daddiu ZERO_64, tconstpool:$in)>;
+ def : MipsPat<(MipsHigher (i64 tglobaltlsaddr:$in)),
+ (Daddiu ZERO_64, tglobaltlsaddr:$in)>;
+ def : MipsPat<(MipsHigher (i64 texternalsym:$in)),
+ (Daddiu ZERO_64, texternalsym:$in)>;
+
+ def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tglobaladdr:$lo))),
+ (Daddiu GPR64:$hi, tglobaladdr:$lo)>;
+ def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tblockaddress:$lo))),
+ (Daddiu GPR64:$hi, tblockaddress:$lo)>;
+ def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tjumptable:$lo))),
+ (Daddiu GPR64:$hi, tjumptable:$lo)>;
+ def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tconstpool:$lo))),
+ (Daddiu GPR64:$hi, tconstpool:$lo)>;
+ def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tglobaltlsaddr:$lo))),
+ (Daddiu GPR64:$hi, tglobaltlsaddr:$lo)>;
+
+ def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tglobaladdr:$lo))),
+ (Daddiu GPR64:$hi, tglobaladdr:$lo)>;
+ def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tblockaddress:$lo))),
+ (Daddiu GPR64:$hi, tblockaddress:$lo)>;
+ def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tjumptable:$lo))),
+ (Daddiu GPR64:$hi, tjumptable:$lo)>;
+ def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tconstpool:$lo))),
+ (Daddiu GPR64:$hi, tconstpool:$lo)>;
+ def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tglobaltlsaddr:$lo))),
+ (Daddiu GPR64:$hi, tglobaltlsaddr:$lo)>;
+
+ def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tglobaladdr:$lo))),
+ (Daddiu GPR64:$hi, tglobaladdr:$lo)>;
+ def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tblockaddress:$lo))),
+ (Daddiu GPR64:$hi, tblockaddress:$lo)>;
+ def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tjumptable:$lo))),
+ (Daddiu GPR64:$hi, tjumptable:$lo)>;
+ def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tconstpool:$lo))),
+ (Daddiu GPR64:$hi, tconstpool:$lo)>;
+ def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tglobaltlsaddr:$lo))),
+ (Daddiu GPR64:$hi, tglobaltlsaddr:$lo)>;
+
+}
+
+// highest/higher/hi/lo relocs
+let AdditionalPredicates = [NotInMicroMips] in
+defm : MipsHighestHigherHiLoRelocs<LUi64, DADDiu>, SYM_64;
+
+def : WrapperPat<tglobaladdr, DADDiu, GPR64>;
+def : WrapperPat<tconstpool, DADDiu, GPR64>;
+def : WrapperPat<texternalsym, DADDiu, GPR64>;
+def : WrapperPat<tblockaddress, DADDiu, GPR64>;
+def : WrapperPat<tjumptable, DADDiu, GPR64>;
+def : WrapperPat<tglobaltlsaddr, DADDiu, GPR64>;
-let AdditionalPredicates = [NotInMicroMips] in {
- def : MipsPat<(MipsLo tglobaladdr:$in), (DADDiu ZERO_64, tglobaladdr:$in)>;
- def : MipsPat<(MipsLo tblockaddress:$in),
- (DADDiu ZERO_64, tblockaddress:$in)>;
- def : MipsPat<(MipsLo tjumptable:$in), (DADDiu ZERO_64, tjumptable:$in)>;
- def : MipsPat<(MipsLo tconstpool:$in), (DADDiu ZERO_64, tconstpool:$in)>;
- def : MipsPat<(MipsLo tglobaltlsaddr:$in),
- (DADDiu ZERO_64, tglobaltlsaddr:$in)>;
- def : MipsPat<(MipsLo texternalsym:$in), (DADDiu ZERO_64, texternalsym:$in)>;
-
- def : MipsPat<(add GPR64:$hi, (MipsLo tglobaladdr:$lo)),
- (DADDiu GPR64:$hi, tglobaladdr:$lo)>;
- def : MipsPat<(add GPR64:$hi, (MipsLo tblockaddress:$lo)),
- (DADDiu GPR64:$hi, tblockaddress:$lo)>;
- def : MipsPat<(add GPR64:$hi, (MipsLo tjumptable:$lo)),
- (DADDiu GPR64:$hi, tjumptable:$lo)>;
- def : MipsPat<(add GPR64:$hi, (MipsLo tconstpool:$lo)),
- (DADDiu GPR64:$hi, tconstpool:$lo)>;
- def : MipsPat<(add GPR64:$hi, (MipsLo tglobaltlsaddr:$lo)),
- (DADDiu GPR64:$hi, tglobaltlsaddr:$lo)>;
-
- def : WrapperPat<tglobaladdr, DADDiu, GPR64>;
- def : WrapperPat<tconstpool, DADDiu, GPR64>;
- def : WrapperPat<texternalsym, DADDiu, GPR64>;
- def : WrapperPat<tblockaddress, DADDiu, GPR64>;
- def : WrapperPat<tjumptable, DADDiu, GPR64>;
- def : WrapperPat<tglobaltlsaddr, DADDiu, GPR64>;
-}
defm : BrcondPats<GPR64, BEQ64, BEQ, BNE64, SLT64, SLTu64, SLTi64, SLTiu64,
ZERO_64>;
@@ -600,6 +669,14 @@ def : MipsPat<(i64 (anyext GPR32:$src)),
def : MipsPat<(i64 (zext GPR32:$src)), (DSRL (DSLL64_32 GPR32:$src), 32)>;
def : MipsPat<(i64 (sext GPR32:$src)), (SLL64_32 GPR32:$src)>;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def : MipsPat<(i64 (zext GPR32:$src)), (DEXT64_32 GPR32:$src, 0, 32)>,
+ ISA_MIPS64R2;
+ def : MipsPat<(i64 (zext (i32 (shl GPR32:$rt, immZExt5:$imm)))),
+ (CINS64_32 GPR32:$rt, imm:$imm, (immZExt5To31 imm:$imm))>,
+ ASE_MIPS64_CNMIPS;
+}
+
// Sign extend in register
def : MipsPat<(i64 (sext_inreg GPR64:$src, i32)),
(SLL64_64 GPR64:$src)>;
@@ -661,10 +738,16 @@ let AdditionalPredicates = [NotInMicroMips] in {
def : MipsInstAlias<"daddu $rs, $imm",
(DADDiu GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm),
0>, ISA_MIPS3;
+
+ defm : OneOrTwoOperandMacroImmediateAlias<"and", ANDi64, GPR64Opnd, imm64>,
+ GPR_64;
+
+ defm : OneOrTwoOperandMacroImmediateAlias<"or", ORi64, GPR64Opnd, imm64>,
+ GPR_64;
+
+ defm : OneOrTwoOperandMacroImmediateAlias<"xor", XORi64, GPR64Opnd, imm64>,
+ GPR_64;
}
-def : MipsInstAlias<"dsll $rd, $rt, $rs",
- (DSLLV GPR64Opnd:$rd, GPR64Opnd:$rt, GPR32Opnd:$rs), 0>,
- ISA_MIPS3;
let AdditionalPredicates = [NotInMicroMips] in {
def : MipsInstAlias<"dneg $rt, $rs",
(DSUB GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rs), 1>,
@@ -707,9 +790,18 @@ def : MipsInstAlias<"dsra $rd, $rt, $rs",
(DSRAV GPR64Opnd:$rd, GPR64Opnd:$rt, GPR32Opnd:$rs), 0>,
ISA_MIPS3;
let AdditionalPredicates = [NotInMicroMips] in {
+ def : MipsInstAlias<"dsll $rd, $rt, $rs",
+ (DSLLV GPR64Opnd:$rd, GPR64Opnd:$rt, GPR32Opnd:$rs), 0>,
+ ISA_MIPS3;
def : MipsInstAlias<"dsrl $rd, $rt, $rs",
(DSRLV GPR64Opnd:$rd, GPR64Opnd:$rt, GPR32Opnd:$rs), 0>,
ISA_MIPS3;
+ def : MipsInstAlias<"dsrl $rd, $rt",
+ (DSRLV GPR64Opnd:$rd, GPR64Opnd:$rd, GPR32Opnd:$rt), 0>,
+ ISA_MIPS3;
+ def : MipsInstAlias<"dsll $rd, $rt",
+ (DSLLV GPR64Opnd:$rd, GPR64Opnd:$rd, GPR32Opnd:$rt), 0>,
+ ISA_MIPS3;
// Two operand (implicit 0 selector) versions:
def : MipsInstAlias<"dmtc0 $rt, $rd",
@@ -741,21 +833,21 @@ def : MipsInstAlias<"bbit1 $rs, $p, $offset",
def : MipsInstAlias<"exts $rt, $rs, $pos, $lenm1",
(EXTS32 GPR64Opnd:$rt, GPR64Opnd:$rs,
uimm5_plus32_normalize:$pos, uimm5:$lenm1), 0>,
- ASE_CNMIPS;
+ ASE_MIPS64_CNMIPS;
def : MipsInstAlias<"exts $rt, $pos, $lenm1",
(EXTS32 GPR64Opnd:$rt, GPR64Opnd:$rt,
uimm5_plus32_normalize:$pos, uimm5:$lenm1), 0>,
- ASE_CNMIPS;
+ ASE_MIPS64_CNMIPS;
// cins with $pos 32-63 in converted to cins32 with $pos 0-31
def : MipsInstAlias<"cins $rt, $rs, $pos, $lenm1",
(CINS32 GPR64Opnd:$rt, GPR64Opnd:$rs,
uimm5_plus32_normalize:$pos, uimm5:$lenm1), 0>,
- ASE_CNMIPS;
+ ASE_MIPS64_CNMIPS;
def : MipsInstAlias<"cins $rt, $pos, $lenm1",
(CINS32 GPR64Opnd:$rt, GPR64Opnd:$rt,
uimm5_plus32_normalize:$pos, uimm5:$lenm1), 0>,
- ASE_CNMIPS;
+ ASE_MIPS64_CNMIPS;
//===----------------------------------------------------------------------===//
// Assembler Pseudo Instructions
@@ -770,3 +862,81 @@ def LoadAddrReg64 : MipsAsmPseudoInst<(outs GPR64Opnd:$rt), (ins mem:$addr),
"dla\t$rt, $addr">;
def LoadAddrImm64 : MipsAsmPseudoInst<(outs GPR64Opnd:$rt), (ins imm64:$imm64),
"dla\t$rt, $imm64">;
+
+def DMULImmMacro : MipsAsmPseudoInst<(outs), (ins GPR64Opnd:$rs, GPR64Opnd:$rt,
+ simm32_relaxed:$imm),
+ "dmul\t$rs, $rt, $imm">,
+ ISA_MIPS3_NOT_32R6_64R6;
+def DMULOMacro : MipsAsmPseudoInst<(outs), (ins GPR64Opnd:$rs, GPR64Opnd:$rt,
+ GPR64Opnd:$rd),
+ "dmulo\t$rs, $rt, $rd">,
+ ISA_MIPS3_NOT_32R6_64R6;
+def DMULOUMacro : MipsAsmPseudoInst<(outs), (ins GPR64Opnd:$rs, GPR64Opnd:$rt,
+ GPR64Opnd:$rd),
+ "dmulou\t$rs, $rt, $rd">,
+ ISA_MIPS3_NOT_32R6_64R6;
+
+def DMULMacro : MipsAsmPseudoInst<(outs), (ins GPR64Opnd:$rs, GPR64Opnd:$rt,
+ GPR64Opnd:$rd),
+ "dmul\t$rs, $rt, $rd"> {
+ let InsnPredicates = [HasMips3, NotMips64r6, NotCnMips];
+}
+
+let AdditionalPredicates = [NotInMicroMips] in {
+ def DSDivMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd),
+ (ins GPR64Opnd:$rs, GPR64Opnd:$rt),
+ "ddiv\t$rd, $rs, $rt">,
+ ISA_MIPS3_NOT_32R6_64R6;
+ def DSDivIMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd),
+ (ins GPR64Opnd:$rs, imm64:$imm),
+ "ddiv\t$rd, $rs, $imm">,
+ ISA_MIPS3_NOT_32R6_64R6;
+ def DUDivMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd),
+ (ins GPR64Opnd:$rs, GPR64Opnd:$rt),
+ "ddivu\t$rd, $rs, $rt">,
+ ISA_MIPS3_NOT_32R6_64R6;
+ def DUDivIMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd),
+ (ins GPR64Opnd:$rs, imm64:$imm),
+ "ddivu\t$rd, $rs, $imm">,
+ ISA_MIPS3_NOT_32R6_64R6;
+
+ // GAS expands 'div' and 'ddiv' differently when the destination
+ // register is $zero and the instruction is in the two operand
+ // form. 'ddiv' gets expanded, while 'div' is not expanded.
+
+ def : MipsInstAlias<"ddiv $rs, $rt", (DSDivMacro GPR64Opnd:$rs,
+ GPR64Opnd:$rs,
+ GPR64Opnd:$rt), 0>,
+ ISA_MIPS3_NOT_32R6_64R6;
+ def : MipsInstAlias<"ddiv $rd, $imm", (DSDivIMacro GPR64Opnd:$rd,
+ GPR64Opnd:$rd,
+ imm64:$imm), 0>,
+ ISA_MIPS3_NOT_32R6_64R6;
+
+ // GAS expands 'divu' and 'ddivu' differently when the destination
+ // register is $zero and the instruction is in the two operand
+ // form. 'ddivu' gets expanded, while 'divu' is not expanded.
+
+ def : MipsInstAlias<"ddivu $rt, $rs", (DUDivMacro GPR64Opnd:$rt,
+ GPR64Opnd:$rt,
+ GPR64Opnd:$rs), 0>,
+ ISA_MIPS3_NOT_32R6_64R6;
+ def : MipsInstAlias<"ddivu $rd, $imm", (DUDivIMacro GPR64Opnd:$rd,
+ GPR64Opnd:$rd,
+ imm64:$imm), 0>,
+ ISA_MIPS3_NOT_32R6_64R6;
+}
+
+def NORImm64 : NORIMM_DESC_BASE<GPR64Opnd, imm64>, GPR_64;
+def : MipsInstAlias<"nor\t$rs, $imm", (NORImm64 GPR64Opnd:$rs, GPR64Opnd:$rs,
+ imm64:$imm)>, GPR_64;
+def SLTImm64 : MipsAsmPseudoInst<(outs GPR64Opnd:$rs),
+ (ins GPR64Opnd:$rt, imm64:$imm),
+ "slt\t$rs, $rt, $imm">, GPR_64;
+def : MipsInstAlias<"slt\t$rs, $imm", (SLTImm64 GPR64Opnd:$rs, GPR64Opnd:$rs,
+ imm64:$imm)>, GPR_64;
+def SLTUImm64 : MipsAsmPseudoInst<(outs GPR64Opnd:$rs),
+ (ins GPR64Opnd:$rt, imm64:$imm),
+ "sltu\t$rs, $rt, $imm">, GPR_64;
+def : MipsInstAlias<"sltu\t$rs, $imm", (SLTUImm64 GPR64Opnd:$rs, GPR64Opnd:$rs,
+ imm64:$imm)>, GPR_64;
diff --git a/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp b/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp
index 04d6529..f7ff7c3 100644
--- a/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp
+++ b/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp
@@ -12,17 +12,18 @@
//
//===----------------------------------------------------------------------===//
+#include "MipsAsmPrinter.h"
#include "InstPrinter/MipsInstPrinter.h"
#include "MCTargetDesc/MipsBaseInfo.h"
#include "MCTargetDesc/MipsMCNaCl.h"
#include "Mips.h"
-#include "MipsAsmPrinter.h"
#include "MipsInstrInfo.h"
#include "MipsMCInstLower.h"
#include "MipsTargetMachine.h"
#include "MipsTargetStreamer.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/BinaryFormat/ELF.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
@@ -39,10 +40,10 @@
#include "llvm/MC/MCELFStreamer.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstBuilder.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCSymbolELF.h"
-#include "llvm/Support/ELF.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
@@ -79,6 +80,9 @@ bool MipsAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
NaClAlignIndirectJumpTargets(MF);
AsmPrinter::runOnMachineFunction(MF);
+
+ emitXRayTable();
+
return true;
}
@@ -132,6 +136,7 @@ void MipsAsmPrinter::emitPseudoIndirectBranch(MCStreamer &OutStreamer,
void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) {
MipsTargetStreamer &TS = getTargetStreamer();
+ unsigned Opc = MI->getOpcode();
TS.forbidModuleDirective();
if (MI->isDebugValue()) {
@@ -143,20 +148,20 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) {
}
// If we just ended a constant pool, mark it as such.
- if (InConstantPool && MI->getOpcode() != Mips::CONSTPOOL_ENTRY) {
+ if (InConstantPool && Opc != Mips::CONSTPOOL_ENTRY) {
OutStreamer->EmitDataRegion(MCDR_DataRegionEnd);
InConstantPool = false;
}
- if (MI->getOpcode() == Mips::CONSTPOOL_ENTRY) {
+ if (Opc == Mips::CONSTPOOL_ENTRY) {
// CONSTPOOL_ENTRY - This instruction represents a floating
- //constant pool in the function. The first operand is the ID#
+ // constant pool in the function. The first operand is the ID#
// for this instruction, the second is the index into the
// MachineConstantPool that this is, the third is the size in
// bytes of this constant pool entry.
// The required alignment is specified on the basic block holding this MI.
//
unsigned LabelId = (unsigned)MI->getOperand(0).getImm();
- unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex();
+ unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex();
// If this is the first entry of the pool, mark it.
if (!InConstantPool) {
@@ -174,6 +179,17 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) {
return;
}
+ switch (Opc) {
+ case Mips::PATCHABLE_FUNCTION_ENTER:
+ LowerPATCHABLE_FUNCTION_ENTER(*MI);
+ return;
+ case Mips::PATCHABLE_FUNCTION_EXIT:
+ LowerPATCHABLE_FUNCTION_EXIT(*MI);
+ return;
+ case Mips::PATCHABLE_TAIL_CALL:
+ LowerPATCHABLE_TAIL_CALL(*MI);
+ return;
+ }
MachineBasicBlock::const_instr_iterator I = MI->getIterator();
MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();
@@ -257,9 +273,9 @@ void MipsAsmPrinter::printSavedRegsBitmask() {
const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
// size of stack area to which FP callee-saved regs are saved.
- unsigned CPURegSize = Mips::GPR32RegClass.getSize();
- unsigned FGR32RegSize = Mips::FGR32RegClass.getSize();
- unsigned AFGR64RegSize = Mips::AFGR64RegClass.getSize();
+ unsigned CPURegSize = TRI->getRegSizeInBits(Mips::GPR32RegClass) / 8;
+ unsigned FGR32RegSize = TRI->getRegSizeInBits(Mips::FGR32RegClass) / 8;
+ unsigned AFGR64RegSize = TRI->getRegSizeInBits(Mips::AFGR64RegClass) / 8;
bool HasAFGR64Reg = false;
unsigned CSFPRegsSize = 0;
@@ -574,6 +590,8 @@ void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
case MipsII::MO_GOT: O << "%got("; break;
case MipsII::MO_ABS_HI: O << "%hi("; break;
case MipsII::MO_ABS_LO: O << "%lo("; break;
+ case MipsII::MO_HIGHER: O << "%higher("; break;
+ case MipsII::MO_HIGHEST: O << "%highest(("; break;
case MipsII::MO_TLSGD: O << "%tlsgd("; break;
case MipsII::MO_GOTTPREL: O << "%gottprel("; break;
case MipsII::MO_TPREL_HI: O << "%tprel_hi("; break;
@@ -698,7 +716,7 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) {
// Ideally it should test for properties of the ABI and not the ABI
// itself.
// For the moment, I'm only correcting enough to make MIPS-IV work.
- if (!isPositionIndependent() && !ABI.IsN64())
+ if (!isPositionIndependent() && STI.hasSym32())
TS.emitDirectiveOptionPic0();
}
@@ -1032,6 +1050,116 @@ void MipsAsmPrinter::EmitEndOfAsmFile(Module &M) {
OutStreamer->SwitchSection(OutContext.getObjectFileInfo()->getTextSection());
}
+void MipsAsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind) {
+ const uint8_t NoopsInSledCount = Subtarget->isGP64bit() ? 15 : 11;
+ // For mips32 we want to emit the following pattern:
+ //
+ // .Lxray_sled_N:
+ // ALIGN
+ // B .tmpN
+ // 11 NOP instructions (44 bytes)
+ // ADDIU T9, T9, 52
+ // .tmpN
+ //
+ // We need the 44 bytes (11 instructions) because at runtime, we'd
+ // be patching over the full 48 bytes (12 instructions) with the following
+ // pattern:
+ //
+ // ADDIU SP, SP, -8
+ // NOP
+ // SW RA, 4(SP)
+ // SW T9, 0(SP)
+ // LUI T9, %hi(__xray_FunctionEntry/Exit)
+ // ORI T9, T9, %lo(__xray_FunctionEntry/Exit)
+ // LUI T0, %hi(function_id)
+ // JALR T9
+ // ORI T0, T0, %lo(function_id)
+ // LW T9, 0(SP)
+ // LW RA, 4(SP)
+ // ADDIU SP, SP, 8
+ //
+ // We add 52 bytes to t9 because we want to adjust the function pointer to
+ // the actual start of function i.e. the address just after the noop sled.
+ // We do this because gp displacement relocation is emitted at the start of
+ // of the function i.e after the nop sled and to correctly calculate the
+ // global offset table address, t9 must hold the address of the instruction
+ // containing the gp displacement relocation.
+ // FIXME: Is this correct for the static relocation model?
+ //
+ // For mips64 we want to emit the following pattern:
+ //
+ // .Lxray_sled_N:
+ // ALIGN
+ // B .tmpN
+ // 15 NOP instructions (60 bytes)
+ // .tmpN
+ //
+ // We need the 60 bytes (15 instructions) because at runtime, we'd
+ // be patching over the full 64 bytes (16 instructions) with the following
+ // pattern:
+ //
+ // DADDIU SP, SP, -16
+ // NOP
+ // SD RA, 8(SP)
+ // SD T9, 0(SP)
+ // LUI T9, %highest(__xray_FunctionEntry/Exit)
+ // ORI T9, T9, %higher(__xray_FunctionEntry/Exit)
+ // DSLL T9, T9, 16
+ // ORI T9, T9, %hi(__xray_FunctionEntry/Exit)
+ // DSLL T9, T9, 16
+ // ORI T9, T9, %lo(__xray_FunctionEntry/Exit)
+ // LUI T0, %hi(function_id)
+ // JALR T9
+ // ADDIU T0, T0, %lo(function_id)
+ // LD T9, 0(SP)
+ // LD RA, 8(SP)
+ // DADDIU SP, SP, 16
+ //
+ OutStreamer->EmitCodeAlignment(4);
+ auto CurSled = OutContext.createTempSymbol("xray_sled_", true);
+ OutStreamer->EmitLabel(CurSled);
+ auto Target = OutContext.createTempSymbol();
+
+ // Emit "B .tmpN" instruction, which jumps over the nop sled to the actual
+ // start of function
+ const MCExpr *TargetExpr = MCSymbolRefExpr::create(
+ Target, MCSymbolRefExpr::VariantKind::VK_None, OutContext);
+ EmitToStreamer(*OutStreamer, MCInstBuilder(Mips::BEQ)
+ .addReg(Mips::ZERO)
+ .addReg(Mips::ZERO)
+ .addExpr(TargetExpr));
+
+ for (int8_t I = 0; I < NoopsInSledCount; I++)
+ EmitToStreamer(*OutStreamer, MCInstBuilder(Mips::SLL)
+ .addReg(Mips::ZERO)
+ .addReg(Mips::ZERO)
+ .addImm(0));
+
+ OutStreamer->EmitLabel(Target);
+
+ if (!Subtarget->isGP64bit()) {
+ EmitToStreamer(*OutStreamer,
+ MCInstBuilder(Mips::ADDiu)
+ .addReg(Mips::T9)
+ .addReg(Mips::T9)
+ .addImm(0x34));
+ }
+
+ recordSled(CurSled, MI, Kind);
+}
+
+void MipsAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI) {
+ EmitSled(MI, SledKind::FUNCTION_ENTER);
+}
+
+void MipsAsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI) {
+ EmitSled(MI, SledKind::FUNCTION_EXIT);
+}
+
+void MipsAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI) {
+ EmitSled(MI, SledKind::TAIL_CALL);
+}
+
void MipsAsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
raw_ostream &OS) {
// TODO: implement
@@ -1039,7 +1167,7 @@ void MipsAsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
// Emit .dtprelword or .dtpreldword directive
// and value for debug thread local expression.
-void MipsAsmPrinter::EmitDebugValue(const MCExpr *Value,
+void MipsAsmPrinter::EmitDebugThreadLocal(const MCExpr *Value,
unsigned Size) const {
switch (Size) {
case 4:
diff --git a/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.h b/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.h
index c5cf524..4699e1b 100644
--- a/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.h
+++ b/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.h
@@ -35,7 +35,21 @@ class LLVM_LIBRARY_VISIBILITY MipsAsmPrinter : public AsmPrinter {
void EmitInstrWithMacroNoAT(const MachineInstr *MI);
+ //===------------------------------------------------------------------===//
+ // XRay implementation
+ //===------------------------------------------------------------------===//
+public:
+ // XRay-specific lowering for Mips.
+ void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI);
+ void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI);
+ void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI);
+ // Helper function that emits the XRay sleds we've collected for a particular
+ // function.
+ void EmitXRayTable();
+
private:
+ void EmitSled(const MachineInstr &MI, SledKind Kind);
+
// tblgen'erated function.
bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,
const MachineInstr *MI);
@@ -140,7 +154,7 @@ public:
void EmitStartOfAsmFile(Module &M) override;
void EmitEndOfAsmFile(Module &M) override;
void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS);
- void EmitDebugValue(const MCExpr *Value, unsigned Size) const override;
+ void EmitDebugThreadLocal(const MCExpr *Value, unsigned Size) const override;
};
}
diff --git a/contrib/llvm/lib/Target/Mips/MipsCCState.cpp b/contrib/llvm/lib/Target/Mips/MipsCCState.cpp
index 7af988c..6a03ee9 100644
--- a/contrib/llvm/lib/Target/Mips/MipsCCState.cpp
+++ b/contrib/llvm/lib/Target/Mips/MipsCCState.cpp
@@ -38,7 +38,7 @@ static bool isF128SoftLibCall(const char *CallSym) {
/// This function returns true if Ty is fp128, {f128} or i128 which was
/// originally a fp128.
-static bool originalTypeIsF128(Type *Ty, const SDNode *CallNode) {
+static bool originalTypeIsF128(const Type *Ty, const char *Func) {
if (Ty->isFP128Ty())
return true;
@@ -46,12 +46,25 @@ static bool originalTypeIsF128(Type *Ty, const SDNode *CallNode) {
Ty->getStructElementType(0)->isFP128Ty())
return true;
- const ExternalSymbolSDNode *ES =
- dyn_cast_or_null<const ExternalSymbolSDNode>(CallNode);
-
// If the Ty is i128 and the function being called is a long double emulation
// routine, then the original type is f128.
- return (ES && Ty->isIntegerTy(128) && isF128SoftLibCall(ES->getSymbol()));
+ return (Func && Ty->isIntegerTy(128) && isF128SoftLibCall(Func));
+}
+
+/// Return true if the original type was vXfXX.
+static bool originalEVTTypeIsVectorFloat(EVT Ty) {
+ if (Ty.isVector() && Ty.getVectorElementType().isFloatingPoint())
+ return true;
+
+ return false;
+}
+
+/// Return true if the original type was vXfXX / vXfXX.
+static bool originalTypeIsVectorFloat(const Type * Ty) {
+ if (Ty->isVectorTy() && Ty->isFPOrFPVectorTy())
+ return true;
+
+ return false;
}
MipsCCState::SpecialCallingConvType
@@ -73,16 +86,16 @@ MipsCCState::getSpecialCallingConvForCallee(const SDNode *Callee,
void MipsCCState::PreAnalyzeCallResultForF128(
const SmallVectorImpl<ISD::InputArg> &Ins,
- const TargetLowering::CallLoweringInfo &CLI) {
+ const Type *RetTy, const char *Call) {
for (unsigned i = 0; i < Ins.size(); ++i) {
OriginalArgWasF128.push_back(
- originalTypeIsF128(CLI.RetTy, CLI.Callee.getNode()));
- OriginalArgWasFloat.push_back(CLI.RetTy->isFloatingPointTy());
+ originalTypeIsF128(RetTy, Call));
+ OriginalArgWasFloat.push_back(RetTy->isFloatingPointTy());
}
}
-/// Identify lowered values that originated from f128 arguments and record
-/// this for use by RetCC_MipsN.
+/// Identify lowered values that originated from f128 or float arguments and
+/// record this for use by RetCC_MipsN.
void MipsCCState::PreAnalyzeReturnForF128(
const SmallVectorImpl<ISD::OutputArg> &Outs) {
const MachineFunction &MF = getMachineFunction();
@@ -94,23 +107,44 @@ void MipsCCState::PreAnalyzeReturnForF128(
}
}
-/// Identify lowered values that originated from f128 arguments and record
+/// Identify lower values that originated from vXfXX and record
+/// this.
+void MipsCCState::PreAnalyzeCallResultForVectorFloat(
+ const SmallVectorImpl<ISD::InputArg> &Ins, const Type *RetTy) {
+ for (unsigned i = 0; i < Ins.size(); ++i) {
+ OriginalRetWasFloatVector.push_back(originalTypeIsVectorFloat(RetTy));
+ }
+}
+
+/// Identify lowered values that originated from vXfXX arguments and record
/// this.
+void MipsCCState::PreAnalyzeReturnForVectorFloat(
+ const SmallVectorImpl<ISD::OutputArg> &Outs) {
+ for (unsigned i = 0; i < Outs.size(); ++i) {
+ ISD::OutputArg Out = Outs[i];
+ OriginalRetWasFloatVector.push_back(
+ originalEVTTypeIsVectorFloat(Out.ArgVT));
+ }
+}
+
+/// Identify lowered values that originated from f128, float and sret to vXfXX
+/// arguments and record this.
void MipsCCState::PreAnalyzeCallOperands(
const SmallVectorImpl<ISD::OutputArg> &Outs,
std::vector<TargetLowering::ArgListEntry> &FuncArgs,
- const SDNode *CallNode) {
+ const char *Func) {
for (unsigned i = 0; i < Outs.size(); ++i) {
- OriginalArgWasF128.push_back(
- originalTypeIsF128(FuncArgs[Outs[i].OrigArgIndex].Ty, CallNode));
- OriginalArgWasFloat.push_back(
- FuncArgs[Outs[i].OrigArgIndex].Ty->isFloatingPointTy());
+ TargetLowering::ArgListEntry FuncArg = FuncArgs[Outs[i].OrigArgIndex];
+
+ OriginalArgWasF128.push_back(originalTypeIsF128(FuncArg.Ty, Func));
+ OriginalArgWasFloat.push_back(FuncArg.Ty->isFloatingPointTy());
+ OriginalArgWasFloatVector.push_back(FuncArg.Ty->isVectorTy());
CallOperandIsFixed.push_back(Outs[i].IsFixed);
}
}
-/// Identify lowered values that originated from f128 arguments and record
-/// this.
+/// Identify lowered values that originated from f128, float and vXfXX arguments
+/// and record this.
void MipsCCState::PreAnalyzeFormalArgumentsForF128(
const SmallVectorImpl<ISD::InputArg> &Ins) {
const MachineFunction &MF = getMachineFunction();
@@ -123,6 +157,7 @@ void MipsCCState::PreAnalyzeFormalArgumentsForF128(
if (Ins[i].Flags.isSRet()) {
OriginalArgWasF128.push_back(false);
OriginalArgWasFloat.push_back(false);
+ OriginalArgWasFloatVector.push_back(false);
continue;
}
@@ -132,5 +167,10 @@ void MipsCCState::PreAnalyzeFormalArgumentsForF128(
OriginalArgWasF128.push_back(
originalTypeIsF128(FuncArg->getType(), nullptr));
OriginalArgWasFloat.push_back(FuncArg->getType()->isFloatingPointTy());
+
+ // The MIPS vector ABI exhibits a corner case of sorts or quirk; if the
+ // first argument is actually an SRet pointer to a vector, then the next
+ // argument slot is $a2.
+ OriginalArgWasFloatVector.push_back(FuncArg->getType()->isVectorTy());
}
}
diff --git a/contrib/llvm/lib/Target/Mips/MipsCCState.h b/contrib/llvm/lib/Target/Mips/MipsCCState.h
index 081c393..2790169 100644
--- a/contrib/llvm/lib/Target/Mips/MipsCCState.h
+++ b/contrib/llvm/lib/Target/Mips/MipsCCState.h
@@ -31,7 +31,7 @@ private:
/// Identify lowered values that originated from f128 arguments and record
/// this for use by RetCC_MipsN.
void PreAnalyzeCallResultForF128(const SmallVectorImpl<ISD::InputArg> &Ins,
- const TargetLowering::CallLoweringInfo &CLI);
+ const Type *RetTy, const char * Func);
/// Identify lowered values that originated from f128 arguments and record
/// this for use by RetCC_MipsN.
@@ -42,19 +42,36 @@ private:
void
PreAnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs,
std::vector<TargetLowering::ArgListEntry> &FuncArgs,
- const SDNode *CallNode);
+ const char *Func);
/// Identify lowered values that originated from f128 arguments and record
- /// this.
+ /// this for use by RetCC_MipsN.
void
PreAnalyzeFormalArgumentsForF128(const SmallVectorImpl<ISD::InputArg> &Ins);
+ void
+ PreAnalyzeCallResultForVectorFloat(const SmallVectorImpl<ISD::InputArg> &Ins,
+ const Type *RetTy);
+
+ void PreAnalyzeFormalArgumentsForVectorFloat(
+ const SmallVectorImpl<ISD::InputArg> &Ins);
+
+ void
+ PreAnalyzeReturnForVectorFloat(const SmallVectorImpl<ISD::OutputArg> &Outs);
+
/// Records whether the value has been lowered from an f128.
SmallVector<bool, 4> OriginalArgWasF128;
/// Records whether the value has been lowered from float.
SmallVector<bool, 4> OriginalArgWasFloat;
+ /// Records whether the value has been lowered from a floating point vector.
+ SmallVector<bool, 4> OriginalArgWasFloatVector;
+
+ /// Records whether the return value has been lowered from a floating point
+ /// vector.
+ SmallVector<bool, 4> OriginalRetWasFloatVector;
+
/// Records whether the value was a fixed argument.
/// See ISD::OutputArg::IsFixed,
SmallVector<bool, 4> CallOperandIsFixed;
@@ -73,11 +90,12 @@ public:
AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs,
CCAssignFn Fn,
std::vector<TargetLowering::ArgListEntry> &FuncArgs,
- const SDNode *CallNode) {
- PreAnalyzeCallOperands(Outs, FuncArgs, CallNode);
+ const char *Func) {
+ PreAnalyzeCallOperands(Outs, FuncArgs, Func);
CCState::AnalyzeCallOperands(Outs, Fn);
OriginalArgWasF128.clear();
OriginalArgWasFloat.clear();
+ OriginalArgWasFloatVector.clear();
CallOperandIsFixed.clear();
}
@@ -96,31 +114,38 @@ public:
CCState::AnalyzeFormalArguments(Ins, Fn);
OriginalArgWasFloat.clear();
OriginalArgWasF128.clear();
+ OriginalArgWasFloatVector.clear();
}
void AnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins,
- CCAssignFn Fn,
- const TargetLowering::CallLoweringInfo &CLI) {
- PreAnalyzeCallResultForF128(Ins, CLI);
+ CCAssignFn Fn, const Type *RetTy,
+ const char *Func) {
+ PreAnalyzeCallResultForF128(Ins, RetTy, Func);
+ PreAnalyzeCallResultForVectorFloat(Ins, RetTy);
CCState::AnalyzeCallResult(Ins, Fn);
OriginalArgWasFloat.clear();
OriginalArgWasF128.clear();
+ OriginalArgWasFloatVector.clear();
}
void AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs,
CCAssignFn Fn) {
PreAnalyzeReturnForF128(Outs);
+ PreAnalyzeReturnForVectorFloat(Outs);
CCState::AnalyzeReturn(Outs, Fn);
OriginalArgWasFloat.clear();
OriginalArgWasF128.clear();
+ OriginalArgWasFloatVector.clear();
}
bool CheckReturn(const SmallVectorImpl<ISD::OutputArg> &ArgsFlags,
CCAssignFn Fn) {
PreAnalyzeReturnForF128(ArgsFlags);
+ PreAnalyzeReturnForVectorFloat(ArgsFlags);
bool Return = CCState::CheckReturn(ArgsFlags, Fn);
OriginalArgWasFloat.clear();
OriginalArgWasF128.clear();
+ OriginalArgWasFloatVector.clear();
return Return;
}
@@ -128,6 +153,12 @@ public:
bool WasOriginalArgFloat(unsigned ValNo) {
return OriginalArgWasFloat[ValNo];
}
+ bool WasOriginalArgVectorFloat(unsigned ValNo) const {
+ return OriginalArgWasFloatVector[ValNo];
+ }
+ bool WasOriginalRetVectorFloat(unsigned ValNo) const {
+ return OriginalRetWasFloatVector[ValNo];
+ }
bool IsCallOperandFixed(unsigned ValNo) { return CallOperandIsFixed[ValNo]; }
SpecialCallingConvType getSpecialCallingConv() { return SpecialCallingConv; }
};
diff --git a/contrib/llvm/lib/Target/Mips/MipsCallingConv.td b/contrib/llvm/lib/Target/Mips/MipsCallingConv.td
index a57cb7b..b5df78f 100644
--- a/contrib/llvm/lib/Target/Mips/MipsCallingConv.td
+++ b/contrib/llvm/lib/Target/Mips/MipsCallingConv.td
@@ -37,6 +37,10 @@ class CCIfOrigArgWasF128<CCAction A>
class CCIfArgIsVarArg<CCAction A>
: CCIf<"!static_cast<MipsCCState *>(&State)->IsCallOperandFixed(ValNo)", A>;
+/// Match if the return was a floating point vector.
+class CCIfOrigArgWasNotVectorFloat<CCAction A>
+ : CCIf<"!static_cast<MipsCCState *>(&State)"
+ "->WasOriginalRetVectorFloat(ValNo)", A>;
/// Match if the special calling conv is the specified value.
class CCIfSpecialCallingConv<string CC, CCAction A>
@@ -93,8 +97,10 @@ def RetCC_MipsO32 : CallingConv<[
// Promote i1/i8/i16 return values to i32.
CCIfType<[i1, i8, i16], CCPromoteToType<i32>>,
- // i32 are returned in registers V0, V1, A0, A1
- CCIfType<[i32], CCAssignToReg<[V0, V1, A0, A1]>>,
+ // i32 are returned in registers V0, V1, A0, A1, unless the original return
+ // type was a vector of floats.
+ CCIfOrigArgWasNotVectorFloat<CCIfType<[i32],
+ CCAssignToReg<[V0, V1, A0, A1]>>>,
// f32 are returned in registers F0, F2
CCIfType<[f32], CCAssignToReg<[F0, F2]>>,
diff --git a/contrib/llvm/lib/Target/Mips/MipsConstantIslandPass.cpp b/contrib/llvm/lib/Target/Mips/MipsConstantIslandPass.cpp
index 08b8ed3..ff43a39 100644
--- a/contrib/llvm/lib/Target/Mips/MipsConstantIslandPass.cpp
+++ b/contrib/llvm/lib/Target/Mips/MipsConstantIslandPass.cpp
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
//
-//
// This pass is used to make Pc relative loads of constants.
// For now, only Mips16 will use this.
//
@@ -19,30 +18,43 @@
// This can be particularly helpful in static relocation mode for embedded
// non-linux targets.
//
-//
+//===----------------------------------------------------------------------===//
#include "Mips.h"
-#include "MCTargetDesc/MipsBaseInfo.h"
#include "Mips16InstrInfo.h"
#include "MipsMachineFunction.h"
-#include "MipsTargetMachine.h"
+#include "MipsSubtarget.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineConstantPool.h"
+#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Function.h"
-#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/Type.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetInstrInfo.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetRegisterInfo.h"
#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <iterator>
+#include <new>
+#include <vector>
using namespace llvm;
@@ -58,7 +70,6 @@ static cl::opt<bool>
AlignConstantIslands("mips-align-constant-islands", cl::Hidden, cl::init(true),
cl::desc("Align constant islands in code"));
-
// Rather than do make check tests with huge amounts of code, we force
// the test to use this amount.
//
@@ -178,7 +189,6 @@ static unsigned int branchMaxOffsets(unsigned int Opcode) {
namespace {
-
typedef MachineBasicBlock::iterator Iter;
typedef MachineBasicBlock::reverse_iterator ReverseIter;
@@ -195,7 +205,6 @@ namespace {
/// tracks a list of users.
class MipsConstantIslands : public MachineFunctionPass {
-
/// BasicBlockInfo - Information about the offset and size of a single
/// basic block.
struct BasicBlockInfo {
@@ -208,14 +217,16 @@ namespace {
///
/// Because worst case padding is used, the computed offset of an aligned
/// block may not actually be aligned.
- unsigned Offset;
+ unsigned Offset = 0;
/// Size - Size of the basic block in bytes. If the block contains
/// inline assembly, this is a worst case estimate.
///
/// The size does not include any alignment padding whether from the
/// beginning of the block, or from an aligned jump table at the end.
- unsigned Size;
+ unsigned Size = 0;
+
+ BasicBlockInfo() = default;
// FIXME: ignore LogAlign for this patch
//
@@ -223,9 +234,6 @@ namespace {
unsigned PO = Offset + Size;
return PO;
}
-
- BasicBlockInfo() : Offset(0), Size(0) {}
-
};
std::vector<BasicBlockInfo> BBInfo;
@@ -257,13 +265,16 @@ namespace {
MachineInstr *MI;
MachineInstr *CPEMI;
MachineBasicBlock *HighWaterMark;
+
private:
unsigned MaxDisp;
unsigned LongFormMaxDisp; // mips16 has 16/32 bit instructions
// with different displacements
unsigned LongFormOpcode;
+
public:
bool NegOk;
+
CPUser(MachineInstr *mi, MachineInstr *cpemi, unsigned maxdisp,
bool neg,
unsigned longformmaxdisp, unsigned longformopcode)
@@ -272,18 +283,22 @@ namespace {
NegOk(neg){
HighWaterMark = CPEMI->getParent();
}
+
/// getMaxDisp - Returns the maximum displacement supported by MI.
unsigned getMaxDisp() const {
unsigned xMaxDisp = ConstantIslandsSmallOffset?
ConstantIslandsSmallOffset: MaxDisp;
return xMaxDisp;
}
+
void setMaxDisp(unsigned val) {
MaxDisp = val;
}
+
unsigned getLongFormMaxDisp() const {
return LongFormMaxDisp;
}
+
unsigned getLongFormOpcode() const {
return LongFormOpcode;
}
@@ -300,6 +315,7 @@ namespace {
MachineInstr *CPEMI;
unsigned CPI;
unsigned RefCount;
+
CPEntry(MachineInstr *cpemi, unsigned cpi, unsigned rc = 0)
: CPEMI(cpemi), CPI(cpi), RefCount(rc) {}
};
@@ -309,7 +325,7 @@ namespace {
/// existed upon entry to this pass), it keeps a vector of entries.
/// Original elements are cloned as we go along; the clones are
/// put in the vector of the original element, but have distinct CPIs.
- std::vector<std::vector<CPEntry> > CPEntries;
+ std::vector<std::vector<CPEntry>> CPEntries;
/// ImmBranch - One per immediate branch, keeping the machine instruction
/// pointer, conditional or unconditional, the max displacement,
@@ -320,6 +336,7 @@ namespace {
unsigned MaxDisp : 31;
bool isCond : 1;
int UncondBr;
+
ImmBranch(MachineInstr *mi, unsigned maxdisp, bool cond, int ubr)
: MI(mi), MaxDisp(maxdisp), isCond(cond), UncondBr(ubr) {}
};
@@ -332,29 +349,27 @@ namespace {
/// the branch fix up pass.
bool HasFarJump;
- const MipsSubtarget *STI;
+ const MipsSubtarget *STI = nullptr;
const Mips16InstrInfo *TII;
MipsFunctionInfo *MFI;
- MachineFunction *MF;
- MachineConstantPool *MCP;
+ MachineFunction *MF = nullptr;
+ MachineConstantPool *MCP = nullptr;
unsigned PICLabelUId;
- bool PrescannedForConstants;
+ bool PrescannedForConstants = false;
void initPICLabelUId(unsigned UId) {
PICLabelUId = UId;
}
-
unsigned createPICLabelUId() {
return PICLabelUId++;
}
public:
static char ID;
- MipsConstantIslands()
- : MachineFunctionPass(ID), STI(nullptr), MF(nullptr), MCP(nullptr),
- PrescannedForConstants(false) {}
+
+ MipsConstantIslands() : MachineFunctionPass(ID) {}
StringRef getPassName() const override { return "Mips Constant Islands"; }
@@ -403,13 +418,11 @@ namespace {
bool fixupUnconditionalBr(ImmBranch &Br);
void prescanForConstants();
-
- private:
-
};
char MipsConstantIslands::ID = 0;
-} // end of anonymous namespace
+
+} // end anonymous namespace
bool MipsConstantIslands::isOffsetInRange
(unsigned UserOffset, unsigned TrialOffset,
@@ -417,20 +430,17 @@ bool MipsConstantIslands::isOffsetInRange
return isOffsetInRange(UserOffset, TrialOffset,
U.getMaxDisp(), U.NegOk);
}
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
/// print block size and offset information - debugging
-void MipsConstantIslands::dumpBBs() {
- DEBUG({
- for (unsigned J = 0, E = BBInfo.size(); J !=E; ++J) {
- const BasicBlockInfo &BBI = BBInfo[J];
- dbgs() << format("%08x BB#%u\t", BBI.Offset, J)
- << format(" size=%#x\n", BBInfo[J].Size);
- }
- });
-}
-/// Returns a pass that converts branches to long branches.
-FunctionPass *llvm::createMipsConstantIslandPass() {
- return new MipsConstantIslands();
+LLVM_DUMP_METHOD void MipsConstantIslands::dumpBBs() {
+ for (unsigned J = 0, E = BBInfo.size(); J !=E; ++J) {
+ const BasicBlockInfo &BBI = BBInfo[J];
+ dbgs() << format("%08x BB#%u\t", BBI.Offset, J)
+ << format(" size=%#x\n", BBInfo[J].Size);
+ }
}
+#endif
bool MipsConstantIslands::runOnMachineFunction(MachineFunction &mf) {
// The intention is for this to be a mips16 only pass for now
@@ -527,7 +537,6 @@ MipsConstantIslands::doInitialPlacement(std::vector<MachineInstr*> &CPEMIs) {
MachineBasicBlock *BB = MF->CreateMachineBasicBlock();
MF->push_back(BB);
-
// MachineConstantPool measures alignment in bytes. We measure in log2(bytes).
unsigned MaxAlign = Log2_32(MCP->getConstantPoolAlignment());
@@ -647,7 +656,6 @@ initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) {
for (MachineFunction::iterator I = MF->begin(), E = MF->end(); I != E; ++I)
computeBlockSize(&*I);
-
// Compute block offsets.
adjustBBOffsetsAfter(&MF->front());
@@ -737,7 +745,6 @@ initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) {
if (Opc == Mips::CONSTPOOL_ENTRY)
continue;
-
// Scan the instructions for constant pool operands.
for (unsigned op = 0, e = MI.getNumOperands(); op != e; ++op)
if (MI.getOperand(op).isCPI()) {
@@ -784,12 +791,9 @@ initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) {
// Instructions can only use one CP entry, don't bother scanning the
// rest of the operands.
break;
-
}
-
}
}
-
}
/// computeBlockSize - Compute the size and some alignment information for MBB.
@@ -921,8 +925,6 @@ MipsConstantIslands::splitBlockBeforeInstr(MachineInstr &MI) {
return NewBB;
}
-
-
/// isOffsetInRange - Checks whether UserOffset (the location of a constant pool
/// reference) is within MaxDisp of TrialOffset (a proposed location of a
/// constant pool entry).
@@ -1337,7 +1339,6 @@ bool MipsConstantIslands::handleConstantPoolUser(unsigned CPUserIndex) {
if (result==1) return false;
else if (result==2) return true;
-
// Look for water where we can place this CPE.
MachineBasicBlock *NewIsland = MF->CreateMachineBasicBlock();
MachineBasicBlock *NewMBB;
@@ -1371,7 +1372,7 @@ bool MipsConstantIslands::handleConstantPoolUser(unsigned CPUserIndex) {
// it. Check for this so it will be removed from the WaterList.
// Also remove any entry from NewWaterList.
MachineBasicBlock *WaterBB = &*--NewMBB->getIterator();
- IP = find(WaterList, WaterBB);
+ IP = llvm::find(WaterList, WaterBB);
if (IP != WaterList.end())
NewWaterList.erase(WaterBB);
@@ -1473,9 +1474,7 @@ bool MipsConstantIslands::removeUnusedCPEntries() {
/// specific BB can fit in MI's displacement field.
bool MipsConstantIslands::isBBInRange
(MachineInstr *MI,MachineBasicBlock *DestBB, unsigned MaxDisp) {
-
-unsigned PCAdj = 4;
-
+ unsigned PCAdj = 4;
unsigned BrOffset = getOffsetOf(MI) + PCAdj;
unsigned DestOffset = BBInfo[DestBB->getNumber()].Offset;
@@ -1553,7 +1552,6 @@ MipsConstantIslands::fixupUnconditionalBr(ImmBranch &Br) {
return true;
}
-
/// fixupConditionalBr - Fix up a conditional branch whose destination is too
/// far away to fit in its displacement field. It is converted to an inverse
/// conditional branch + an unconditional branch to the destination.
@@ -1614,7 +1612,6 @@ MipsConstantIslands::fixupConditionalBr(ImmBranch &Br) {
}
}
-
if (NeedSplit) {
splitBlockBeforeInstr(*MI);
// No need for the branch to the next block. We're adding an unconditional
@@ -1654,7 +1651,6 @@ MipsConstantIslands::fixupConditionalBr(ImmBranch &Br) {
return true;
}
-
void MipsConstantIslands::prescanForConstants() {
unsigned J = 0;
(void)J;
@@ -1667,11 +1663,11 @@ void MipsConstantIslands::prescanForConstants() {
PrescannedForConstants = true;
DEBUG(dbgs() << "constant island constant " << *I << "\n");
J = I->getNumOperands();
- DEBUG(dbgs() << "num operands " << J << "\n");
+ DEBUG(dbgs() << "num operands " << J << "\n");
MachineOperand& Literal = I->getOperand(1);
if (Literal.isImm()) {
int64_t V = Literal.getImm();
- DEBUG(dbgs() << "literal " << V << "\n");
+ DEBUG(dbgs() << "literal " << V << "\n");
Type *Int32Ty =
Type::getInt32Ty(MF->getFunction()->getContext());
const Constant *C = ConstantInt::get(Int32Ty, V);
@@ -1692,3 +1688,8 @@ void MipsConstantIslands::prescanForConstants() {
}
}
}
+
+/// Returns a pass that converts branches to long branches.
+FunctionPass *llvm::createMipsConstantIslandPass() {
+ return new MipsConstantIslands();
+}
diff --git a/contrib/llvm/lib/Target/Mips/MipsDSPInstrInfo.td b/contrib/llvm/lib/Target/Mips/MipsDSPInstrInfo.td
index ac9a81b..c238a65 100644
--- a/contrib/llvm/lib/Target/Mips/MipsDSPInstrInfo.td
+++ b/contrib/llvm/lib/Target/Mips/MipsDSPInstrInfo.td
@@ -19,6 +19,7 @@ def immZExt4 : ImmLeaf<i32, [{return isUInt<4>(Imm);}]>;
def immZExt8 : ImmLeaf<i32, [{return isUInt<8>(Imm);}]>;
def immZExt10 : ImmLeaf<i32, [{return isUInt<10>(Imm);}]>;
def immSExt6 : ImmLeaf<i32, [{return isInt<6>(Imm);}]>;
+def immSExt10 : ImmLeaf<i32, [{return isInt<10>(Imm);}]>;
// Mips-specific dsp nodes
def SDT_MipsExtr : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisSameAs<0, 1>,
@@ -851,8 +852,8 @@ class PACKRL_PH_DESC : CMP_EQ_QB_R3_DESC_BASE<"packrl.ph", int_mips_packrl_ph,
class REPL_QB_DESC : REPL_DESC_BASE<"repl.qb", int_mips_repl_qb, uimm8,
immZExt8, NoItinerary, DSPROpnd>;
-class REPL_PH_DESC : REPL_DESC_BASE<"repl.ph", int_mips_repl_ph, uimm10,
- immZExt10, NoItinerary, DSPROpnd>;
+class REPL_PH_DESC : REPL_DESC_BASE<"repl.ph", int_mips_repl_ph, simm10,
+ immSExt10, NoItinerary, DSPROpnd>;
class REPLV_QB_DESC : ABSQ_S_PH_R2_DESC_BASE<"replv.qb", int_mips_repl_qb,
NoItinerary, DSPROpnd, GPR32Opnd>;
diff --git a/contrib/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp b/contrib/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp
index c821084..4a34e31 100644
--- a/contrib/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp
+++ b/contrib/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp
@@ -14,21 +14,39 @@
#include "MCTargetDesc/MipsMCNaCl.h"
#include "Mips.h"
#include "MipsInstrInfo.h"
+#include "MipsSubtarget.h"
#include "MipsTargetMachine.h"
#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/ValueTracking.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
+#include "llvm/MC/MCInstrDesc.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/CodeGen.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"
+#include <algorithm>
+#include <cassert>
+#include <iterator>
+#include <memory>
+#include <utility>
using namespace llvm;
@@ -84,6 +102,7 @@ static cl::opt<CompactBranchPolicy> MipsCompactBranchPolicy(
);
namespace {
+
typedef MachineBasicBlock::iterator Iter;
typedef MachineBasicBlock::reverse_iterator ReverseIter;
typedef SmallDenseMap<MachineBasicBlock*, MachineInstr*, 2> BB2BrMap;
@@ -91,6 +110,7 @@ namespace {
class RegDefsUses {
public:
RegDefsUses(const TargetRegisterInfo &TRI);
+
void init(const MachineInstr &MI);
/// This function sets all caller-saved registers in Defs.
@@ -120,18 +140,18 @@ namespace {
/// Base class for inspecting loads and stores.
class InspectMemInstr {
public:
- InspectMemInstr(bool ForbidMemInstr_)
- : OrigSeenLoad(false), OrigSeenStore(false), SeenLoad(false),
- SeenStore(false), ForbidMemInstr(ForbidMemInstr_) {}
+ InspectMemInstr(bool ForbidMemInstr_) : ForbidMemInstr(ForbidMemInstr_) {}
+ virtual ~InspectMemInstr() = default;
/// Return true if MI cannot be moved to delay slot.
bool hasHazard(const MachineInstr &MI);
- virtual ~InspectMemInstr() {}
-
protected:
/// Flags indicating whether loads or stores have been seen.
- bool OrigSeenLoad, OrigSeenStore, SeenLoad, SeenStore;
+ bool OrigSeenLoad = false;
+ bool OrigSeenStore = false;
+ bool SeenLoad = false;
+ bool SeenStore = false;
/// Memory instructions are not allowed to move to delay slot if this flag
/// is true.
@@ -145,6 +165,7 @@ namespace {
class NoMemInstr : public InspectMemInstr {
public:
NoMemInstr() : InspectMemInstr(true) {}
+
private:
bool hasHazard_(const MachineInstr &MI) override { return true; }
};
@@ -153,6 +174,7 @@ namespace {
class LoadFromStackOrConst : public InspectMemInstr {
public:
LoadFromStackOrConst() : InspectMemInstr(false) {}
+
private:
bool hasHazard_(const MachineInstr &MI) override;
};
@@ -183,17 +205,18 @@ namespace {
/// Flags indicating whether loads or stores with no underlying objects have
/// been seen.
- bool SeenNoObjLoad, SeenNoObjStore;
+ bool SeenNoObjLoad = false;
+ bool SeenNoObjStore = false;
};
class Filler : public MachineFunctionPass {
public:
- Filler(TargetMachine &tm)
- : MachineFunctionPass(ID), TM(tm) { }
+ Filler() : MachineFunctionPass(ID), TM(nullptr) {}
StringRef getPassName() const override { return "Mips Delay Slot Filler"; }
bool runOnMachineFunction(MachineFunction &F) override {
+ TM = &F.getTarget();
bool Changed = false;
for (MachineFunction::iterator FI = F.begin(), FE = F.end();
FI != FE; ++FI)
@@ -267,12 +290,14 @@ namespace {
bool terminateSearch(const MachineInstr &Candidate) const;
- TargetMachine &TM;
+ const TargetMachine *TM;
static char ID;
};
+
char Filler::ID = 0;
-} // end of anonymous namespace
+
+} // end anonymous namespace
static bool hasUnoccupiedSlot(const MachineInstr *MI) {
return MI->hasDelaySlot() && !MI->isBundledWithSucc();
@@ -361,7 +386,7 @@ void RegDefsUses::setCallerSaved(const MachineInstr &MI) {
void RegDefsUses::setUnallocatableRegs(const MachineFunction &MF) {
BitVector AllocSet = TRI.getAllocatableSet(MF);
- for (int R = AllocSet.find_first(); R != -1; R = AllocSet.find_next(R))
+ for (unsigned R : AllocSet.set_bits())
for (MCRegAliasIterator AI(R, &TRI, false); AI.isValid(); ++AI)
AllocSet.set(*AI);
@@ -458,8 +483,7 @@ bool LoadFromStackOrConst::hasHazard_(const MachineInstr &MI) {
}
MemDefsUses::MemDefsUses(const DataLayout &DL, const MachineFrameInfo *MFI_)
- : InspectMemInstr(false), MFI(MFI_), DL(DL), SeenNoObjLoad(false),
- SeenNoObjStore(false) {}
+ : InspectMemInstr(false), MFI(MFI_), DL(DL) {}
bool MemDefsUses::hasHazard_(const MachineInstr &MI) {
bool HasHazard = false;
@@ -540,7 +564,7 @@ Iter Filler::replaceWithCompactBranch(MachineBasicBlock &MBB, Iter Branch,
// For given opcode returns opcode of corresponding instruction with short
// delay slot.
-// For the pseudo TAILCALL*_MM instrunctions return the short delay slot
+// For the pseudo TAILCALL*_MM instructions return the short delay slot
// form. Unfortunately, TAILCALL<->b16 is denied as b16 has a limited range
// that is too short to make use of for tail calls.
static int getEquivalentCallShort(int Opcode) {
@@ -586,7 +610,7 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
Changed = true;
// Delay slot filling is disabled at -O0.
- if (!DisableDelaySlotFiller && (TM.getOptLevel() != CodeGenOpt::None)) {
+ if (!DisableDelaySlotFiller && (TM->getOptLevel() != CodeGenOpt::None)) {
bool Filled = false;
if (MipsCompactBranchPolicy.getValue() != CB_Always ||
@@ -646,12 +670,6 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
return Changed;
}
-/// createMipsDelaySlotFillerPass - Returns a pass that fills in delay
-/// slots in Mips MachineFunctions
-FunctionPass *llvm::createMipsDelaySlotFillerPass(MipsTargetMachine &tm) {
- return new Filler(tm);
-}
-
template<typename IterTy>
bool Filler::searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End,
RegDefsUses &RegDU, InspectMemInstr& IM, Iter Slot,
@@ -889,3 +907,7 @@ bool Filler::terminateSearch(const MachineInstr &Candidate) const {
Candidate.isPosition() || Candidate.isInlineAsm() ||
Candidate.hasUnmodeledSideEffects());
}
+
+/// createMipsDelaySlotFillerPass - Returns a pass that fills in delay
+/// slots in Mips MachineFunctions
+FunctionPass *llvm::createMipsDelaySlotFillerPass() { return new Filler(); }
diff --git a/contrib/llvm/lib/Target/Mips/MipsFastISel.cpp b/contrib/llvm/lib/Target/Mips/MipsFastISel.cpp
index a44192f..f79cb0e 100644
--- a/contrib/llvm/lib/Target/Mips/MipsFastISel.cpp
+++ b/contrib/llvm/lib/Target/Mips/MipsFastISel.cpp
@@ -1,4 +1,4 @@
-//===-- MipsFastISel.cpp - Mips FastISel implementation --------------------===//
+//===-- MipsFastISel.cpp - Mips FastISel implementation -------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,24 +14,62 @@
///
//===----------------------------------------------------------------------===//
+#include "MCTargetDesc/MipsABIInfo.h"
+#include "MCTargetDesc/MipsBaseInfo.h"
#include "MipsCCState.h"
-#include "MipsInstrInfo.h"
#include "MipsISelLowering.h"
+#include "MipsInstrInfo.h"
#include "MipsMachineFunction.h"
-#include "MipsRegisterInfo.h"
#include "MipsSubtarget.h"
#include "MipsTargetMachine.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/FastISel.h"
#include "llvm/CodeGen/FunctionLoweringInfo.h"
+#include "llvm/CodeGen/ISDOpcodes.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/MachineValueType.h"
+#include "llvm/CodeGen/ValueTypes.h"
+#include "llvm/IR/Attributes.h"
+#include "llvm/IR/CallingConv.h"
+#include "llvm/IR/Constant.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Function.h"
#include "llvm/IR/GetElementPtrTypeIterator.h"
-#include "llvm/IR/GlobalAlias.h"
+#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/InstrTypes.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Operator.h"
+#include "llvm/IR/Type.h"
+#include "llvm/IR/User.h"
+#include "llvm/IR/Value.h"
+#include "llvm/MC/MCInstrDesc.h"
+#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSymbol.h"
-#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Target/TargetLowering.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <new>
#define DEBUG_TYPE "mips-fastisel"
@@ -47,35 +85,40 @@ class MipsFastISel final : public FastISel {
typedef enum { RegBase, FrameIndexBase } BaseKind;
private:
- BaseKind Kind;
+ BaseKind Kind = RegBase;
union {
unsigned Reg;
int FI;
} Base;
- int64_t Offset;
+ int64_t Offset = 0;
- const GlobalValue *GV;
+ const GlobalValue *GV = nullptr;
public:
// Innocuous defaults for our address.
- Address() : Kind(RegBase), Offset(0), GV(0) { Base.Reg = 0; }
+ Address() { Base.Reg = 0; }
+
void setKind(BaseKind K) { Kind = K; }
BaseKind getKind() const { return Kind; }
bool isRegBase() const { return Kind == RegBase; }
bool isFIBase() const { return Kind == FrameIndexBase; }
+
void setReg(unsigned Reg) {
assert(isRegBase() && "Invalid base register access!");
Base.Reg = Reg;
}
+
unsigned getReg() const {
assert(isRegBase() && "Invalid base register access!");
return Base.Reg;
}
+
void setFI(unsigned FI) {
assert(isFIBase() && "Invalid base frame index access!");
Base.FI = FI;
}
+
unsigned getFI() const {
assert(isFIBase() && "Invalid base frame index access!");
return Base.FI;
@@ -165,14 +208,17 @@ private:
MachineInstrBuilder emitInst(unsigned Opc) {
return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
}
+
MachineInstrBuilder emitInst(unsigned Opc, unsigned DstReg) {
return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc),
DstReg);
}
+
MachineInstrBuilder emitInstStore(unsigned Opc, unsigned SrcReg,
unsigned MemReg, int64_t MemOffset) {
return emitInst(Opc).addReg(SrcReg).addReg(MemReg).addImm(MemOffset);
}
+
MachineInstrBuilder emitInstLoad(unsigned Opc, unsigned DstReg,
unsigned MemReg, int64_t MemOffset) {
return emitInst(Opc, DstReg).addReg(MemReg).addImm(MemOffset);
@@ -198,6 +244,7 @@ private:
bool processCallArgs(CallLoweringInfo &CLI, SmallVectorImpl<MVT> &ArgVTs,
unsigned &NumBytes);
bool finishCall(CallLoweringInfo &CLI, MVT RetVT, unsigned NumBytes);
+
const MipsABIInfo &getABI() const {
return static_cast<const MipsTargetMachine &>(TM).getABI();
}
@@ -220,7 +267,8 @@ public:
#include "MipsGenFastISel.inc"
};
-} // end anonymous namespace.
+
+} // end anonymous namespace
static bool CC_Mips(unsigned ValNo, MVT ValVT, MVT LocVT,
CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags,
@@ -414,7 +462,6 @@ unsigned MipsFastISel::fastMaterializeConstant(const Constant *C) {
}
bool MipsFastISel::computeAddress(const Value *Obj, Address &Addr) {
-
const User *U = nullptr;
unsigned Opcode = Instruction::UserOp1;
if (const Instruction *I = dyn_cast<Instruction>(Obj)) {
@@ -432,10 +479,9 @@ bool MipsFastISel::computeAddress(const Value *Obj, Address &Addr) {
switch (Opcode) {
default:
break;
- case Instruction::BitCast: {
+ case Instruction::BitCast:
// Look through bitcasts.
return computeAddress(U->getOperand(0), Addr);
- }
case Instruction::GetElementPtr: {
Address SavedAddr = Addr;
int64_t TmpOffset = Addr.getOffset();
@@ -451,7 +497,7 @@ bool MipsFastISel::computeAddress(const Value *Obj, Address &Addr) {
TmpOffset += SL->getElementOffset(Idx);
} else {
uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType());
- for (;;) {
+ while (true) {
if (const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) {
// Constant-offset addressing.
TmpOffset += CI->getSExtValue() * S;
@@ -613,14 +659,12 @@ bool MipsFastISel::emitCmp(unsigned ResultReg, const CmpInst *CI) {
emitInst(Mips::SLTu, ResultReg).addReg(Mips::ZERO).addReg(TempReg);
break;
}
- case CmpInst::ICMP_UGT: {
+ case CmpInst::ICMP_UGT:
emitInst(Mips::SLTu, ResultReg).addReg(RightReg).addReg(LeftReg);
break;
- }
- case CmpInst::ICMP_ULT: {
+ case CmpInst::ICMP_ULT:
emitInst(Mips::SLTu, ResultReg).addReg(LeftReg).addReg(RightReg);
break;
- }
case CmpInst::ICMP_UGE: {
unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
emitInst(Mips::SLTu, TempReg).addReg(LeftReg).addReg(RightReg);
@@ -633,14 +677,12 @@ bool MipsFastISel::emitCmp(unsigned ResultReg, const CmpInst *CI) {
emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
break;
}
- case CmpInst::ICMP_SGT: {
+ case CmpInst::ICMP_SGT:
emitInst(Mips::SLT, ResultReg).addReg(RightReg).addReg(LeftReg);
break;
- }
- case CmpInst::ICMP_SLT: {
+ case CmpInst::ICMP_SLT:
emitInst(Mips::SLT, ResultReg).addReg(LeftReg).addReg(RightReg);
break;
- }
case CmpInst::ICMP_SGE: {
unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
emitInst(Mips::SLT, TempReg).addReg(LeftReg).addReg(RightReg);
@@ -709,6 +751,7 @@ bool MipsFastISel::emitCmp(unsigned ResultReg, const CmpInst *CI) {
}
return true;
}
+
bool MipsFastISel::emitLoad(MVT VT, unsigned &ResultReg, Address &Addr,
unsigned Alignment) {
//
@@ -716,35 +759,30 @@ bool MipsFastISel::emitLoad(MVT VT, unsigned &ResultReg, Address &Addr,
//
unsigned Opc;
switch (VT.SimpleTy) {
- case MVT::i32: {
+ case MVT::i32:
ResultReg = createResultReg(&Mips::GPR32RegClass);
Opc = Mips::LW;
break;
- }
- case MVT::i16: {
+ case MVT::i16:
ResultReg = createResultReg(&Mips::GPR32RegClass);
Opc = Mips::LHu;
break;
- }
- case MVT::i8: {
+ case MVT::i8:
ResultReg = createResultReg(&Mips::GPR32RegClass);
Opc = Mips::LBu;
break;
- }
- case MVT::f32: {
+ case MVT::f32:
if (UnsupportedFPMode)
return false;
ResultReg = createResultReg(&Mips::FGR32RegClass);
Opc = Mips::LWC1;
break;
- }
- case MVT::f64: {
+ case MVT::f64:
if (UnsupportedFPMode)
return false;
ResultReg = createResultReg(&Mips::AFGR64RegClass);
Opc = Mips::LDC1;
break;
- }
default:
return false;
}
@@ -1095,7 +1133,7 @@ bool MipsFastISel::processCallArgs(CallLoweringInfo &CLI,
if (NumBytes < 16)
NumBytes = 16;
- emitInst(Mips::ADJCALLSTACKDOWN).addImm(16);
+ emitInst(Mips::ADJCALLSTACKDOWN).addImm(16).addImm(0);
// Process the args.
MVT firstMVT;
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
@@ -1222,8 +1260,11 @@ bool MipsFastISel::finishCall(CallLoweringInfo &CLI, MVT RetVT,
emitInst(Mips::ADJCALLSTACKUP).addImm(16).addImm(0);
if (RetVT != MVT::isVoid) {
SmallVector<CCValAssign, 16> RVLocs;
- CCState CCInfo(CC, false, *FuncInfo.MF, RVLocs, *Context);
- CCInfo.AnalyzeCallResult(RetVT, RetCC_Mips);
+ MipsCCState CCInfo(CC, false, *FuncInfo.MF, RVLocs, *Context);
+
+ CCInfo.AnalyzeCallResult(CLI.Ins, RetCC_Mips, CLI.RetTy,
+ CLI.Symbol ? CLI.Symbol->getName().data()
+ : nullptr);
// Only handle a single return value.
if (RVLocs.size() != 1)
@@ -1286,11 +1327,10 @@ bool MipsFastISel::fastLowerArguments() {
// Only handle simple cases. i.e. All arguments are directly mapped to
// registers of the appropriate type.
SmallVector<AllocatedReg, 4> Allocation;
- unsigned Idx = 1;
for (const auto &FormalArg : F->args()) {
- if (F->getAttributes().hasAttribute(Idx, Attribute::InReg) ||
- F->getAttributes().hasAttribute(Idx, Attribute::StructRet) ||
- F->getAttributes().hasAttribute(Idx, Attribute::ByVal)) {
+ if (FormalArg.hasAttribute(Attribute::InReg) ||
+ FormalArg.hasAttribute(Attribute::StructRet) ||
+ FormalArg.hasAttribute(Attribute::ByVal)) {
DEBUG(dbgs() << ".. gave up (inreg, structret, byval)\n");
return false;
}
@@ -1302,7 +1342,8 @@ bool MipsFastISel::fastLowerArguments() {
}
EVT ArgVT = TLI.getValueType(DL, ArgTy);
- DEBUG(dbgs() << ".. " << (Idx - 1) << ": " << ArgVT.getEVTString() << "\n");
+ DEBUG(dbgs() << ".. " << FormalArg.getArgNo() << ": "
+ << ArgVT.getEVTString() << "\n");
if (!ArgVT.isSimple()) {
DEBUG(dbgs() << ".. .. gave up (not a simple type)\n");
return false;
@@ -1312,8 +1353,8 @@ bool MipsFastISel::fastLowerArguments() {
case MVT::i1:
case MVT::i8:
case MVT::i16:
- if (!F->getAttributes().hasAttribute(Idx, Attribute::SExt) &&
- !F->getAttributes().hasAttribute(Idx, Attribute::ZExt)) {
+ if (!FormalArg.hasAttribute(Attribute::SExt) &&
+ !FormalArg.hasAttribute(Attribute::ZExt)) {
// It must be any extend, this shouldn't happen for clang-generated IR
// so just fall back on SelectionDAG.
DEBUG(dbgs() << ".. .. gave up (i8/i16 arg is not extended)\n");
@@ -1334,7 +1375,7 @@ bool MipsFastISel::fastLowerArguments() {
break;
case MVT::i32:
- if (F->getAttributes().hasAttribute(Idx, Attribute::ZExt)) {
+ if (FormalArg.hasAttribute(Attribute::ZExt)) {
// The O32 ABI does not permit a zero-extended i32.
DEBUG(dbgs() << ".. .. gave up (i32 arg is zero extended)\n");
return false;
@@ -1397,23 +1438,20 @@ bool MipsFastISel::fastLowerArguments() {
DEBUG(dbgs() << ".. .. gave up (unknown type)\n");
return false;
}
-
- ++Idx;
}
- Idx = 0;
for (const auto &FormalArg : F->args()) {
- unsigned SrcReg = Allocation[Idx].Reg;
- unsigned DstReg = FuncInfo.MF->addLiveIn(SrcReg, Allocation[Idx].RC);
+ unsigned ArgNo = FormalArg.getArgNo();
+ unsigned SrcReg = Allocation[ArgNo].Reg;
+ unsigned DstReg = FuncInfo.MF->addLiveIn(SrcReg, Allocation[ArgNo].RC);
// FIXME: Unfortunately it's necessary to emit a copy from the livein copy.
// Without this, EmitLiveInCopies may eliminate the livein if its only
// use is a bitcast (which isn't turned into an instruction).
- unsigned ResultReg = createResultReg(Allocation[Idx].RC);
+ unsigned ResultReg = createResultReg(Allocation[ArgNo].RC);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(TargetOpcode::COPY), ResultReg)
.addReg(DstReg, getKillRegState(true));
updateValueMap(&FormalArg, ResultReg);
- ++Idx;
}
// Calculate the size of the incoming arguments area.
@@ -1730,6 +1768,7 @@ bool MipsFastISel::selectTrunc(const Instruction *I) {
updateValueMap(I, SrcReg);
return true;
}
+
bool MipsFastISel::selectIntExt(const Instruction *I) {
Type *DestTy = I->getType();
Value *Src = I->getOperand(0);
@@ -1757,6 +1796,7 @@ bool MipsFastISel::selectIntExt(const Instruction *I) {
updateValueMap(I, ResultReg);
return true;
}
+
bool MipsFastISel::emitIntSExt32r1(MVT SrcVT, unsigned SrcReg, MVT DestVT,
unsigned DestReg) {
unsigned ShiftAmt;
@@ -2074,8 +2114,10 @@ unsigned MipsFastISel::fastEmitInst_rr(unsigned MachineInstOpcode,
}
namespace llvm {
+
FastISel *Mips::createFastISel(FunctionLoweringInfo &funcInfo,
const TargetLibraryInfo *libInfo) {
return new MipsFastISel(funcInfo, libInfo);
}
-}
+
+} // end namespace llvm
diff --git a/contrib/llvm/lib/Target/Mips/MipsFrameLowering.cpp b/contrib/llvm/lib/Target/Mips/MipsFrameLowering.cpp
index b2cf039..ef05166 100644
--- a/contrib/llvm/lib/Target/Mips/MipsFrameLowering.cpp
+++ b/contrib/llvm/lib/Target/Mips/MipsFrameLowering.cpp
@@ -119,7 +119,7 @@ uint64_t MipsFrameLowering::estimateStackSize(const MachineFunction &MF) const {
// Conservatively assume all callee-saved registers will be saved.
for (const MCPhysReg *R = TRI.getCalleeSavedRegs(&MF); *R; ++R) {
- unsigned Size = TRI.getMinimalPhysRegClass(*R)->getSize();
+ unsigned Size = TRI.getSpillSize(*TRI.getMinimalPhysRegClass(*R));
Offset = alignTo(Offset + Size, Size);
}
diff --git a/contrib/llvm/lib/Target/Mips/MipsHazardSchedule.cpp b/contrib/llvm/lib/Target/Mips/MipsHazardSchedule.cpp
index 31b8612..f6fcf6e 100644
--- a/contrib/llvm/lib/Target/Mips/MipsHazardSchedule.cpp
+++ b/contrib/llvm/lib/Target/Mips/MipsHazardSchedule.cpp
@@ -36,7 +36,7 @@
///
/// A) A previous pass has created a compact branch directly.
/// B) Transforming a delay slot branch into compact branch. This case can be
-/// difficult to process as lookahead for hazards is insufficent, as
+/// difficult to process as lookahead for hazards is insufficient, as
/// backwards delay slot fillling can also produce hazards in previously
/// processed instuctions.
///
@@ -103,23 +103,24 @@ static Iter getNextMachineInstrInBB(Iter Position) {
// Find the next real instruction from the current position, looking through
// basic block boundaries.
-static Iter getNextMachineInstr(Iter Position, MachineBasicBlock *Parent) {
+static std::pair<Iter, bool> getNextMachineInstr(Iter Position, MachineBasicBlock * Parent) {
if (Position == Parent->end()) {
- MachineBasicBlock *Succ = Parent->getNextNode();
- if (Succ != nullptr && Parent->isSuccessor(Succ)) {
- Position = Succ->begin();
- Parent = Succ;
- } else {
- llvm_unreachable(
- "Should have identified the end of the function earlier!");
- }
+ do {
+ MachineBasicBlock *Succ = Parent->getNextNode();
+ if (Succ != nullptr && Parent->isSuccessor(Succ)) {
+ Position = Succ->begin();
+ Parent = Succ;
+ } else {
+ return std::make_pair(Position, true);
+ }
+ } while (Parent->empty());
}
Iter Instr = getNextMachineInstrInBB(Position);
if (Instr == Parent->end()) {
return getNextMachineInstr(Instr, Parent);
}
- return Instr;
+ return std::make_pair(Instr, false);
}
bool MipsHazardSchedule::runOnMachineFunction(MachineFunction &MF) {
@@ -145,7 +146,9 @@ bool MipsHazardSchedule::runOnMachineFunction(MachineFunction &MF) {
bool LastInstInFunction =
std::next(I) == FI->end() && std::next(FI) == MF.end();
if (!LastInstInFunction) {
- Inst = getNextMachineInstr(std::next(I), &*FI);
+ std::pair<Iter, bool> Res = getNextMachineInstr(std::next(I), &*FI);
+ LastInstInFunction |= Res.second;
+ Inst = Res.first;
}
if (LastInstInFunction || !TII->SafeInForbiddenSlot(*Inst)) {
diff --git a/contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp b/contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp
index 9c511bd..20319f8 100644
--- a/contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -22,12 +22,12 @@
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/CodeGen/CallingConvLower.h"
+#include "llvm/CodeGen/FunctionLoweringInfo.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/CodeGen/FunctionLoweringInfo.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/IR/CallingConv.h"
@@ -71,6 +71,48 @@ static bool isShiftedMask(uint64_t I, uint64_t &Pos, uint64_t &Size) {
return true;
}
+// The MIPS MSA ABI passes vector arguments in the integer register set.
+// The number of integer registers used is dependant on the ABI used.
+MVT MipsTargetLowering::getRegisterTypeForCallingConv(MVT VT) const {
+ if (VT.isVector() && Subtarget.hasMSA())
+ return Subtarget.isABI_O32() ? MVT::i32 : MVT::i64;
+ return MipsTargetLowering::getRegisterType(VT);
+}
+
+MVT MipsTargetLowering::getRegisterTypeForCallingConv(LLVMContext &Context,
+ EVT VT) const {
+ if (VT.isVector()) {
+ if (Subtarget.isABI_O32()) {
+ return MVT::i32;
+ } else {
+ return (VT.getSizeInBits() == 32) ? MVT::i32 : MVT::i64;
+ }
+ }
+ return MipsTargetLowering::getRegisterType(Context, VT);
+}
+
+unsigned MipsTargetLowering::getNumRegistersForCallingConv(LLVMContext &Context,
+ EVT VT) const {
+ if (VT.isVector())
+ return std::max((VT.getSizeInBits() / (Subtarget.isABI_O32() ? 32 : 64)),
+ 1U);
+ return MipsTargetLowering::getNumRegisters(Context, VT);
+}
+
+unsigned MipsTargetLowering::getVectorTypeBreakdownForCallingConv(
+ LLVMContext &Context, EVT VT, EVT &IntermediateVT,
+ unsigned &NumIntermediates, MVT &RegisterVT) const {
+
+ // Break down vector types to either 2 i64s or 4 i32s.
+ RegisterVT = getRegisterTypeForCallingConv(Context, VT) ;
+ IntermediateVT = RegisterVT;
+ NumIntermediates = VT.getSizeInBits() < RegisterVT.getSizeInBits()
+ ? VT.getVectorNumElements()
+ : VT.getSizeInBits() / RegisterVT.getSizeInBits();
+
+ return NumIntermediates;
+}
+
SDValue MipsTargetLowering::getGlobalReg(SelectionDAG &DAG, EVT Ty) const {
MipsFunctionInfo *FI = DAG.getMachineFunction().getInfo<MipsFunctionInfo>();
return DAG.getRegister(FI->getGlobalBaseReg(), Ty);
@@ -112,8 +154,11 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const {
case MipsISD::FIRST_NUMBER: break;
case MipsISD::JmpLink: return "MipsISD::JmpLink";
case MipsISD::TailCall: return "MipsISD::TailCall";
+ case MipsISD::Highest: return "MipsISD::Highest";
+ case MipsISD::Higher: return "MipsISD::Higher";
case MipsISD::Hi: return "MipsISD::Hi";
case MipsISD::Lo: return "MipsISD::Lo";
+ case MipsISD::GotHi: return "MipsISD::GotHi";
case MipsISD::GPRel: return "MipsISD::GPRel";
case MipsISD::ThreadPointer: return "MipsISD::ThreadPointer";
case MipsISD::Ret: return "MipsISD::Ret";
@@ -144,6 +189,7 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const {
case MipsISD::Sync: return "MipsISD::Sync";
case MipsISD::Ext: return "MipsISD::Ext";
case MipsISD::Ins: return "MipsISD::Ins";
+ case MipsISD::CIns: return "MipsISD::CIns";
case MipsISD::LWL: return "MipsISD::LWL";
case MipsISD::LWR: return "MipsISD::LWR";
case MipsISD::SWL: return "MipsISD::SWL";
@@ -318,6 +364,18 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM,
setOperationAction(ISD::UDIV, MVT::i64, Expand);
setOperationAction(ISD::UREM, MVT::i64, Expand);
+ if (!(Subtarget.hasDSP() && Subtarget.hasMips32r2())) {
+ setOperationAction(ISD::ADDC, MVT::i32, Expand);
+ setOperationAction(ISD::ADDE, MVT::i32, Expand);
+ }
+
+ setOperationAction(ISD::ADDC, MVT::i64, Expand);
+ setOperationAction(ISD::ADDE, MVT::i64, Expand);
+ setOperationAction(ISD::SUBC, MVT::i32, Expand);
+ setOperationAction(ISD::SUBE, MVT::i32, Expand);
+ setOperationAction(ISD::SUBC, MVT::i64, Expand);
+ setOperationAction(ISD::SUBE, MVT::i64, Expand);
+
// Operations not directly supported by Mips.
setOperationAction(ISD::BR_CC, MVT::f32, Expand);
setOperationAction(ISD::BR_CC, MVT::f64, Expand);
@@ -358,7 +416,6 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM,
setOperationAction(ISD::FCOS, MVT::f64, Expand);
setOperationAction(ISD::FSINCOS, MVT::f32, Expand);
setOperationAction(ISD::FSINCOS, MVT::f64, Expand);
- setOperationAction(ISD::FPOWI, MVT::f32, Expand);
setOperationAction(ISD::FPOW, MVT::f32, Expand);
setOperationAction(ISD::FPOW, MVT::f64, Expand);
setOperationAction(ISD::FLOG, MVT::f32, Expand);
@@ -424,7 +481,9 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM,
setTargetDAGCombine(ISD::AND);
setTargetDAGCombine(ISD::OR);
setTargetDAGCombine(ISD::ADD);
+ setTargetDAGCombine(ISD::SUB);
setTargetDAGCombine(ISD::AssertZext);
+ setTargetDAGCombine(ISD::SHL);
if (ABI.IsO32()) {
// These libcalls are not available in 32-bit.
@@ -466,8 +525,9 @@ MipsTargetLowering::createFastISel(FunctionLoweringInfo &funcInfo,
!Subtarget.hasMips32r6() && !Subtarget.inMips16Mode() &&
!Subtarget.inMicroMipsMode();
- // Disable if we don't generate PIC or the ABI isn't O32.
- if (!TM.isPositionIndependent() || !TM.getABI().IsO32())
+ // Disable if either of the following is true:
+ // We do not generate PIC, the ABI is not O32, LargeGOT is being used.
+ if (!TM.isPositionIndependent() || !TM.getABI().IsO32() || LargeGOT)
UseFastISel = false;
return UseFastISel ? Mips::createFastISel(funcInfo, libInfo) : nullptr;
@@ -699,41 +759,81 @@ static SDValue performCMovFPCombine(SDNode *N, SelectionDAG &DAG,
static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG,
TargetLowering::DAGCombinerInfo &DCI,
const MipsSubtarget &Subtarget) {
- // Pattern match EXT.
- // $dst = and ((sra or srl) $src , pos), (2**size - 1)
- // => ext $dst, $src, size, pos
if (DCI.isBeforeLegalizeOps() || !Subtarget.hasExtractInsert())
return SDValue();
- SDValue ShiftRight = N->getOperand(0), Mask = N->getOperand(1);
- unsigned ShiftRightOpc = ShiftRight.getOpcode();
-
- // Op's first operand must be a shift right.
- if (ShiftRightOpc != ISD::SRA && ShiftRightOpc != ISD::SRL)
- return SDValue();
+ SDValue FirstOperand = N->getOperand(0);
+ unsigned FirstOperandOpc = FirstOperand.getOpcode();
+ SDValue Mask = N->getOperand(1);
+ EVT ValTy = N->getValueType(0);
+ SDLoc DL(N);
- // The second operand of the shift must be an immediate.
+ uint64_t Pos = 0, SMPos, SMSize;
ConstantSDNode *CN;
- if (!(CN = dyn_cast<ConstantSDNode>(ShiftRight.getOperand(1))))
- return SDValue();
-
- uint64_t Pos = CN->getZExtValue();
- uint64_t SMPos, SMSize;
+ SDValue NewOperand;
+ unsigned Opc;
// Op's second operand must be a shifted mask.
if (!(CN = dyn_cast<ConstantSDNode>(Mask)) ||
!isShiftedMask(CN->getZExtValue(), SMPos, SMSize))
return SDValue();
- // Return if the shifted mask does not start at bit 0 or the sum of its size
- // and Pos exceeds the word's size.
- EVT ValTy = N->getValueType(0);
- if (SMPos != 0 || Pos + SMSize > ValTy.getSizeInBits())
- return SDValue();
+ if (FirstOperandOpc == ISD::SRA || FirstOperandOpc == ISD::SRL) {
+ // Pattern match EXT.
+ // $dst = and ((sra or srl) $src , pos), (2**size - 1)
+ // => ext $dst, $src, pos, size
+
+ // The second operand of the shift must be an immediate.
+ if (!(CN = dyn_cast<ConstantSDNode>(FirstOperand.getOperand(1))))
+ return SDValue();
+
+ Pos = CN->getZExtValue();
+
+ // Return if the shifted mask does not start at bit 0 or the sum of its size
+ // and Pos exceeds the word's size.
+ if (SMPos != 0 || Pos + SMSize > ValTy.getSizeInBits())
+ return SDValue();
+
+ Opc = MipsISD::Ext;
+ NewOperand = FirstOperand.getOperand(0);
+ } else if (FirstOperandOpc == ISD::SHL && Subtarget.hasCnMips()) {
+ // Pattern match CINS.
+ // $dst = and (shl $src , pos), mask
+ // => cins $dst, $src, pos, size
+ // mask is a shifted mask with consecutive 1's, pos = shift amount,
+ // size = population count.
+
+ // The second operand of the shift must be an immediate.
+ if (!(CN = dyn_cast<ConstantSDNode>(FirstOperand.getOperand(1))))
+ return SDValue();
+
+ Pos = CN->getZExtValue();
+
+ if (SMPos != Pos || Pos >= ValTy.getSizeInBits() || SMSize >= 32 ||
+ Pos + SMSize > ValTy.getSizeInBits())
+ return SDValue();
+
+ NewOperand = FirstOperand.getOperand(0);
+ // SMSize is 'location' (position) in this case, not size.
+ SMSize--;
+ Opc = MipsISD::CIns;
+ } else {
+ // Pattern match EXT.
+ // $dst = and $src, (2**size - 1) , if size > 16
+ // => ext $dst, $src, pos, size , pos = 0
- SDLoc DL(N);
- return DAG.getNode(MipsISD::Ext, DL, ValTy,
- ShiftRight.getOperand(0),
+ // If the mask is <= 0xffff, andi can be used instead.
+ if (CN->getZExtValue() <= 0xffff)
+ return SDValue();
+
+ // Return if the mask doesn't start at position 0.
+ if (SMPos)
+ return SDValue();
+
+ Opc = MipsISD::Ext;
+ NewOperand = FirstOperand;
+ }
+ return DAG.getNode(Opc, DL, ValTy, NewOperand,
DAG.getConstant(Pos, DL, MVT::i32),
DAG.getConstant(SMSize, DL, MVT::i32));
}
@@ -750,7 +850,7 @@ static SDValue performORCombine(SDNode *N, SelectionDAG &DAG,
SDValue And0 = N->getOperand(0), And1 = N->getOperand(1);
uint64_t SMPos0, SMSize0, SMPos1, SMSize1;
- ConstantSDNode *CN;
+ ConstantSDNode *CN, *CN1;
// See if Op's first operand matches (and $src1 , mask0).
if (And0.getOpcode() != ISD::AND)
@@ -761,47 +861,202 @@ static SDValue performORCombine(SDNode *N, SelectionDAG &DAG,
return SDValue();
// See if Op's second operand matches (and (shl $src, pos), mask1).
- if (And1.getOpcode() != ISD::AND)
+ if (And1.getOpcode() == ISD::AND &&
+ And1.getOperand(0).getOpcode() == ISD::SHL) {
+
+ if (!(CN = dyn_cast<ConstantSDNode>(And1.getOperand(1))) ||
+ !isShiftedMask(CN->getZExtValue(), SMPos1, SMSize1))
+ return SDValue();
+
+ // The shift masks must have the same position and size.
+ if (SMPos0 != SMPos1 || SMSize0 != SMSize1)
+ return SDValue();
+
+ SDValue Shl = And1.getOperand(0);
+
+ if (!(CN = dyn_cast<ConstantSDNode>(Shl.getOperand(1))))
+ return SDValue();
+
+ unsigned Shamt = CN->getZExtValue();
+
+ // Return if the shift amount and the first bit position of mask are not the
+ // same.
+ EVT ValTy = N->getValueType(0);
+ if ((Shamt != SMPos0) || (SMPos0 + SMSize0 > ValTy.getSizeInBits()))
+ return SDValue();
+
+ SDLoc DL(N);
+ return DAG.getNode(MipsISD::Ins, DL, ValTy, Shl.getOperand(0),
+ DAG.getConstant(SMPos0, DL, MVT::i32),
+ DAG.getConstant(SMSize0, DL, MVT::i32),
+ And0.getOperand(0));
+ } else {
+ // Pattern match DINS.
+ // $dst = or (and $src, mask0), mask1
+ // where mask0 = ((1 << SMSize0) -1) << SMPos0
+ // => dins $dst, $src, pos, size
+ if (~CN->getSExtValue() == ((((int64_t)1 << SMSize0) - 1) << SMPos0) &&
+ ((SMSize0 + SMPos0 <= 64 && Subtarget.hasMips64r2()) ||
+ (SMSize0 + SMPos0 <= 32))) {
+ // Check if AND instruction has constant as argument
+ bool isConstCase = And1.getOpcode() != ISD::AND;
+ if (And1.getOpcode() == ISD::AND) {
+ if (!(CN1 = dyn_cast<ConstantSDNode>(And1->getOperand(1))))
+ return SDValue();
+ } else {
+ if (!(CN1 = dyn_cast<ConstantSDNode>(N->getOperand(1))))
+ return SDValue();
+ }
+ // Don't generate INS if constant OR operand doesn't fit into bits
+ // cleared by constant AND operand.
+ if (CN->getSExtValue() & CN1->getSExtValue())
+ return SDValue();
+
+ SDLoc DL(N);
+ EVT ValTy = N->getOperand(0)->getValueType(0);
+ SDValue Const1;
+ SDValue SrlX;
+ if (!isConstCase) {
+ Const1 = DAG.getConstant(SMPos0, DL, MVT::i32);
+ SrlX = DAG.getNode(ISD::SRL, DL, And1->getValueType(0), And1, Const1);
+ }
+ return DAG.getNode(
+ MipsISD::Ins, DL, N->getValueType(0),
+ isConstCase
+ ? DAG.getConstant(CN1->getSExtValue() >> SMPos0, DL, ValTy)
+ : SrlX,
+ DAG.getConstant(SMPos0, DL, MVT::i32),
+ DAG.getConstant(ValTy.getSizeInBits() / 8 < 8 ? SMSize0 & 31
+ : SMSize0,
+ DL, MVT::i32),
+ And0->getOperand(0));
+
+ }
return SDValue();
+ }
+}
- if (!(CN = dyn_cast<ConstantSDNode>(And1.getOperand(1))) ||
- !isShiftedMask(CN->getZExtValue(), SMPos1, SMSize1))
+static SDValue performMADD_MSUBCombine(SDNode *ROOTNode, SelectionDAG &CurDAG,
+ const MipsSubtarget &Subtarget) {
+ // ROOTNode must have a multiplication as an operand for the match to be
+ // successful.
+ if (ROOTNode->getOperand(0).getOpcode() != ISD::MUL &&
+ ROOTNode->getOperand(1).getOpcode() != ISD::MUL)
return SDValue();
- // The shift masks must have the same position and size.
- if (SMPos0 != SMPos1 || SMSize0 != SMSize1)
+ // We don't handle vector types here.
+ if (ROOTNode->getValueType(0).isVector())
return SDValue();
- SDValue Shl = And1.getOperand(0);
- if (Shl.getOpcode() != ISD::SHL)
+ // For MIPS64, madd / msub instructions are inefficent to use with 64 bit
+ // arithmetic. E.g.
+ // (add (mul a b) c) =>
+ // let res = (madd (mthi (drotr c 32))x(mtlo c) a b) in
+ // MIPS64: (or (dsll (mfhi res) 32) (dsrl (dsll (mflo res) 32) 32)
+ // or
+ // MIPS64R2: (dins (mflo res) (mfhi res) 32 32)
+ //
+ // The overhead of setting up the Hi/Lo registers and reassembling the
+ // result makes this a dubious optimzation for MIPS64. The core of the
+ // problem is that Hi/Lo contain the upper and lower 32 bits of the
+ // operand and result.
+ //
+ // It requires a chain of 4 add/mul for MIPS64R2 to get better code
+ // density than doing it naively, 5 for MIPS64. Additionally, using
+ // madd/msub on MIPS64 requires the operands actually be 32 bit sign
+ // extended operands, not true 64 bit values.
+ //
+ // FIXME: For the moment, disable this completely for MIPS64.
+ if (Subtarget.hasMips64())
return SDValue();
- if (!(CN = dyn_cast<ConstantSDNode>(Shl.getOperand(1))))
+ SDValue Mult = ROOTNode->getOperand(0).getOpcode() == ISD::MUL
+ ? ROOTNode->getOperand(0)
+ : ROOTNode->getOperand(1);
+
+ SDValue AddOperand = ROOTNode->getOperand(0).getOpcode() == ISD::MUL
+ ? ROOTNode->getOperand(1)
+ : ROOTNode->getOperand(0);
+
+ // Transform this to a MADD only if the user of this node is the add.
+ // If there are other users of the mul, this function returns here.
+ if (!Mult.hasOneUse())
return SDValue();
- unsigned Shamt = CN->getZExtValue();
+ // maddu and madd are unusual instructions in that on MIPS64 bits 63..31
+ // must be in canonical form, i.e. sign extended. For MIPS32, the operands
+ // of the multiply must have 32 or more sign bits, otherwise we cannot
+ // perform this optimization. We have to check this here as we're performing
+ // this optimization pre-legalization.
+ SDValue MultLHS = Mult->getOperand(0);
+ SDValue MultRHS = Mult->getOperand(1);
- // Return if the shift amount and the first bit position of mask are not the
- // same.
- EVT ValTy = N->getValueType(0);
- if ((Shamt != SMPos0) || (SMPos0 + SMSize0 > ValTy.getSizeInBits()))
+ bool IsSigned = MultLHS->getOpcode() == ISD::SIGN_EXTEND &&
+ MultRHS->getOpcode() == ISD::SIGN_EXTEND;
+ bool IsUnsigned = MultLHS->getOpcode() == ISD::ZERO_EXTEND &&
+ MultRHS->getOpcode() == ISD::ZERO_EXTEND;
+
+ if (!IsSigned && !IsUnsigned)
return SDValue();
- SDLoc DL(N);
- return DAG.getNode(MipsISD::Ins, DL, ValTy, Shl.getOperand(0),
- DAG.getConstant(SMPos0, DL, MVT::i32),
- DAG.getConstant(SMSize0, DL, MVT::i32),
- And0.getOperand(0));
+ // Initialize accumulator.
+ SDLoc DL(ROOTNode);
+ SDValue TopHalf;
+ SDValue BottomHalf;
+ BottomHalf = CurDAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, AddOperand,
+ CurDAG.getIntPtrConstant(0, DL));
+
+ TopHalf = CurDAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, AddOperand,
+ CurDAG.getIntPtrConstant(1, DL));
+ SDValue ACCIn = CurDAG.getNode(MipsISD::MTLOHI, DL, MVT::Untyped,
+ BottomHalf,
+ TopHalf);
+
+ // Create MipsMAdd(u) / MipsMSub(u) node.
+ bool IsAdd = ROOTNode->getOpcode() == ISD::ADD;
+ unsigned Opcode = IsAdd ? (IsUnsigned ? MipsISD::MAddu : MipsISD::MAdd)
+ : (IsUnsigned ? MipsISD::MSubu : MipsISD::MSub);
+ SDValue MAddOps[3] = {
+ CurDAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Mult->getOperand(0)),
+ CurDAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Mult->getOperand(1)), ACCIn};
+ EVT VTs[2] = {MVT::i32, MVT::i32};
+ SDValue MAdd = CurDAG.getNode(Opcode, DL, VTs, MAddOps);
+
+ SDValue ResLo = CurDAG.getNode(MipsISD::MFLO, DL, MVT::i32, MAdd);
+ SDValue ResHi = CurDAG.getNode(MipsISD::MFHI, DL, MVT::i32, MAdd);
+ SDValue Combined =
+ CurDAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, ResLo, ResHi);
+ return Combined;
+}
+
+static SDValue performSUBCombine(SDNode *N, SelectionDAG &DAG,
+ TargetLowering::DAGCombinerInfo &DCI,
+ const MipsSubtarget &Subtarget) {
+ // (sub v0 (mul v1, v2)) => (msub v1, v2, v0)
+ if (DCI.isBeforeLegalizeOps()) {
+ if (Subtarget.hasMips32() && !Subtarget.hasMips32r6() &&
+ !Subtarget.inMips16Mode() && N->getValueType(0) == MVT::i64)
+ return performMADD_MSUBCombine(N, DAG, Subtarget);
+
+ return SDValue();
+ }
+
+ return SDValue();
}
static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG,
TargetLowering::DAGCombinerInfo &DCI,
const MipsSubtarget &Subtarget) {
- // (add v0, (add v1, abs_lo(tjt))) => (add (add v0, v1), abs_lo(tjt))
+ // (add v0 (mul v1, v2)) => (madd v1, v2, v0)
+ if (DCI.isBeforeLegalizeOps()) {
+ if (Subtarget.hasMips32() && !Subtarget.hasMips32r6() &&
+ !Subtarget.inMips16Mode() && N->getValueType(0) == MVT::i64)
+ return performMADD_MSUBCombine(N, DAG, Subtarget);
- if (DCI.isBeforeLegalizeOps())
return SDValue();
+ }
+ // (add v0, (add v1, abs_lo(tjt))) => (add (add v0, v1), abs_lo(tjt))
SDValue Add = N->getOperand(1);
if (Add.getOpcode() != ISD::ADD)
@@ -852,6 +1107,58 @@ static SDValue performAssertZextCombine(SDNode *N, SelectionDAG &DAG,
return SDValue();
}
+
+static SDValue performSHLCombine(SDNode *N, SelectionDAG &DAG,
+ TargetLowering::DAGCombinerInfo &DCI,
+ const MipsSubtarget &Subtarget) {
+ // Pattern match CINS.
+ // $dst = shl (and $src , imm), pos
+ // => cins $dst, $src, pos, size
+
+ if (DCI.isBeforeLegalizeOps() || !Subtarget.hasCnMips())
+ return SDValue();
+
+ SDValue FirstOperand = N->getOperand(0);
+ unsigned FirstOperandOpc = FirstOperand.getOpcode();
+ SDValue SecondOperand = N->getOperand(1);
+ EVT ValTy = N->getValueType(0);
+ SDLoc DL(N);
+
+ uint64_t Pos = 0, SMPos, SMSize;
+ ConstantSDNode *CN;
+ SDValue NewOperand;
+
+ // The second operand of the shift must be an immediate.
+ if (!(CN = dyn_cast<ConstantSDNode>(SecondOperand)))
+ return SDValue();
+
+ Pos = CN->getZExtValue();
+
+ if (Pos >= ValTy.getSizeInBits())
+ return SDValue();
+
+ if (FirstOperandOpc != ISD::AND)
+ return SDValue();
+
+ // AND's second operand must be a shifted mask.
+ if (!(CN = dyn_cast<ConstantSDNode>(FirstOperand.getOperand(1))) ||
+ !isShiftedMask(CN->getZExtValue(), SMPos, SMSize))
+ return SDValue();
+
+ // Return if the shifted mask does not start at bit 0 or the sum of its size
+ // and Pos exceeds the word's size.
+ if (SMPos != 0 || SMSize > 32 || Pos + SMSize > ValTy.getSizeInBits())
+ return SDValue();
+
+ NewOperand = FirstOperand.getOperand(0);
+ // SMSize is 'location' (position) in this case, not size.
+ SMSize--;
+
+ return DAG.getNode(MipsISD::CIns, DL, ValTy, NewOperand,
+ DAG.getConstant(Pos, DL, MVT::i32),
+ DAG.getConstant(SMSize, DL, MVT::i32));
+}
+
SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
const {
SelectionDAG &DAG = DCI.DAG;
@@ -875,6 +1182,10 @@ SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
return performADDCombine(N, DAG, DCI, Subtarget);
case ISD::AssertZext:
return performAssertZextCombine(N, DAG, DCI, Subtarget);
+ case ISD::SHL:
+ return performSHLCombine(N, DAG, DCI, Subtarget);
+ case ISD::SUB:
+ return performSUBCombine(N, DAG, DCI, Subtarget);
}
return SDValue();
@@ -1733,7 +2044,7 @@ SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op,
GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);
const GlobalValue *GV = N->getGlobal();
- if (!isPositionIndependent() && !ABI.IsN64()) {
+ if (!isPositionIndependent()) {
const MipsTargetObjectFile *TLOF =
static_cast<const MipsTargetObjectFile *>(
getTargetMachine().getObjFileLowering());
@@ -1742,8 +2053,10 @@ SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op,
// %gp_rel relocation
return getAddrGPRel(N, SDLoc(N), Ty, DAG);
- // %hi/%lo relocation
- return getAddrNonPIC(N, SDLoc(N), Ty, DAG);
+ // %hi/%lo relocation
+ return Subtarget.hasSym32() ? getAddrNonPIC(N, SDLoc(N), Ty, DAG)
+ // %highest/%higher/%hi/%lo relocation
+ : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG);
}
// Every other architecture would use shouldAssumeDSOLocal in here, but
@@ -1777,8 +2090,9 @@ SDValue MipsTargetLowering::lowerBlockAddress(SDValue Op,
BlockAddressSDNode *N = cast<BlockAddressSDNode>(Op);
EVT Ty = Op.getValueType();
- if (!isPositionIndependent() && !ABI.IsN64())
- return getAddrNonPIC(N, SDLoc(N), Ty, DAG);
+ if (!isPositionIndependent())
+ return Subtarget.hasSym32() ? getAddrNonPIC(N, SDLoc(N), Ty, DAG)
+ : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG);
return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64());
}
@@ -1820,8 +2134,9 @@ lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const
Args.push_back(Entry);
TargetLowering::CallLoweringInfo CLI(DAG);
- CLI.setDebugLoc(DL).setChain(DAG.getEntryNode())
- .setCallee(CallingConv::C, PtrTy, TlsGetAddr, std::move(Args));
+ CLI.setDebugLoc(DL)
+ .setChain(DAG.getEntryNode())
+ .setLibCallee(CallingConv::C, PtrTy, TlsGetAddr, std::move(Args));
std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);
SDValue Ret = CallResult.first;
@@ -1870,8 +2185,9 @@ lowerJumpTable(SDValue Op, SelectionDAG &DAG) const
JumpTableSDNode *N = cast<JumpTableSDNode>(Op);
EVT Ty = Op.getValueType();
- if (!isPositionIndependent() && !ABI.IsN64())
- return getAddrNonPIC(N, SDLoc(N), Ty, DAG);
+ if (!isPositionIndependent())
+ return Subtarget.hasSym32() ? getAddrNonPIC(N, SDLoc(N), Ty, DAG)
+ : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG);
return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64());
}
@@ -1882,7 +2198,7 @@ lowerConstantPool(SDValue Op, SelectionDAG &DAG) const
ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op);
EVT Ty = Op.getValueType();
- if (!isPositionIndependent() && !ABI.IsN64()) {
+ if (!isPositionIndependent()) {
const MipsTargetObjectFile *TLOF =
static_cast<const MipsTargetObjectFile *>(
getTargetMachine().getObjFileLowering());
@@ -1892,10 +2208,11 @@ lowerConstantPool(SDValue Op, SelectionDAG &DAG) const
// %gp_rel relocation
return getAddrGPRel(N, SDLoc(N), Ty, DAG);
- return getAddrNonPIC(N, SDLoc(N), Ty, DAG);
+ return Subtarget.hasSym32() ? getAddrNonPIC(N, SDLoc(N), Ty, DAG)
+ : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG);
}
- return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64());
+ return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64());
}
SDValue MipsTargetLowering::lowerVASTART(SDValue Op, SelectionDAG &DAG) const {
@@ -2410,6 +2727,11 @@ SDValue MipsTargetLowering::lowerFP_TO_SINT(SDValue Op,
// yet to hold an argument. Otherwise, use A2, A3 and stack. If A1 is
// not used, it must be shadowed. If only A3 is available, shadow it and
// go to stack.
+// vXiX - Received as scalarized i32s, passed in A0 - A3 and the stack.
+// vXf32 - Passed in either a pair of registers {A0, A1}, {A2, A3} or {A0 - A3}
+// with the remainder spilled to the stack.
+// vXf64 - Passed in either {A0, A1, A2, A3} or {A2, A3} and in both cases
+// spilling the remainder to the stack.
//
// For vararg functions, all arguments are passed in A0, A1, A2, A3 and stack.
//===----------------------------------------------------------------------===//
@@ -2421,8 +2743,13 @@ static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT,
State.getMachineFunction().getSubtarget());
static const MCPhysReg IntRegs[] = { Mips::A0, Mips::A1, Mips::A2, Mips::A3 };
+
+ const MipsCCState * MipsState = static_cast<MipsCCState *>(&State);
+
static const MCPhysReg F32Regs[] = { Mips::F12, Mips::F14 };
+ static const MCPhysReg FloatVectorIntRegs[] = { Mips::A0, Mips::A2 };
+
// Do not process byval args here.
if (ArgFlags.isByVal())
return true;
@@ -2460,8 +2787,26 @@ static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT,
State.getFirstUnallocated(F32Regs) != ValNo;
unsigned OrigAlign = ArgFlags.getOrigAlign();
bool isI64 = (ValVT == MVT::i32 && OrigAlign == 8);
-
- if (ValVT == MVT::i32 || (ValVT == MVT::f32 && AllocateFloatsInIntReg)) {
+ bool isVectorFloat = MipsState->WasOriginalArgVectorFloat(ValNo);
+
+ // The MIPS vector ABI for floats passes them in a pair of registers
+ if (ValVT == MVT::i32 && isVectorFloat) {
+ // This is the start of an vector that was scalarized into an unknown number
+ // of components. It doesn't matter how many there are. Allocate one of the
+ // notional 8 byte aligned registers which map onto the argument stack, and
+ // shadow the register lost to alignment requirements.
+ if (ArgFlags.isSplit()) {
+ Reg = State.AllocateReg(FloatVectorIntRegs);
+ if (Reg == Mips::A2)
+ State.AllocateReg(Mips::A1);
+ else if (Reg == 0)
+ State.AllocateReg(Mips::A3);
+ } else {
+ // If we're an intermediate component of the split, we can just attempt to
+ // allocate a register directly.
+ Reg = State.AllocateReg(IntRegs);
+ }
+ } else if (ValVT == MVT::i32 || (ValVT == MVT::f32 && AllocateFloatsInIntReg)) {
Reg = State.AllocateReg(IntRegs);
// If this is the first part of an i64 arg,
// the allocated register must be either A0 or A2.
@@ -2645,7 +2990,10 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
// caller side but removing it breaks the frame size calculation.
CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(CallConv), 1);
- CCInfo.AnalyzeCallOperands(Outs, CC_Mips, CLI.getArgs(), Callee.getNode());
+ const ExternalSymbolSDNode *ES =
+ dyn_cast_or_null<const ExternalSymbolSDNode>(Callee.getNode());
+ CCInfo.AnalyzeCallOperands(Outs, CC_Mips, CLI.getArgs(),
+ ES ? ES->getSymbol() : nullptr);
// Get a count of how many bytes are to be pushed on the stack.
unsigned NextStackOffset = CCInfo.getNextStackOffset();
@@ -2679,7 +3027,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
SDValue NextStackOffsetVal = DAG.getIntPtrConstant(NextStackOffset, DL, true);
if (!IsTailCall)
- Chain = DAG.getCALLSEQ_START(Chain, NextStackOffsetVal, DL);
+ Chain = DAG.getCALLSEQ_START(Chain, NextStackOffset, 0, DL);
SDValue StackPtr =
DAG.getCopyFromReg(Chain, DL, ABI.IsN64() ? Mips::SP_64 : Mips::SP,
@@ -2796,14 +3144,27 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
// If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
// direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
// node so that legalize doesn't hack it.
- bool IsPICCall = (ABI.IsN64() || IsPIC); // true if calls are translated to
- // jalr $25
+
SDValue CalleeLo;
EVT Ty = Callee.getValueType();
bool GlobalOrExternal = false, IsCallReloc = false;
+ // The long-calls feature is ignored in case of PIC.
+ // While we do not support -mshared / -mno-shared properly,
+ // ignore long-calls in case of -mabicalls too.
+ if (Subtarget.useLongCalls() && !Subtarget.isABICalls() && !IsPIC) {
+ // Get the address of the callee into a register to prevent
+ // using of the `jal` instruction for the direct call.
+ if (auto *N = dyn_cast<GlobalAddressSDNode>(Callee))
+ Callee = Subtarget.hasSym32() ? getAddrNonPIC(N, SDLoc(N), Ty, DAG)
+ : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG);
+ else if (auto *N = dyn_cast<ExternalSymbolSDNode>(Callee))
+ Callee = Subtarget.hasSym32() ? getAddrNonPIC(N, SDLoc(N), Ty, DAG)
+ : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG);
+ }
+
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
- if (IsPICCall) {
+ if (IsPIC) {
const GlobalValue *Val = G->getGlobal();
InternalLinkage = Val->hasInternalLinkage();
@@ -2828,7 +3189,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
const char *Sym = S->getSymbol();
- if (!ABI.IsN64() && !IsPIC) // !N64 && static
+ if (!IsPIC) // static
Callee = DAG.getTargetExternalSymbol(
Sym, getPointerTy(DAG.getDataLayout()), MipsII::MO_NO_FLAG);
else if (LargeGOT) {
@@ -2836,7 +3197,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
MipsII::MO_CALL_LO16, Chain,
FuncInfo->callPtrInfo(Sym));
IsCallReloc = true;
- } else { // N64 || PIC
+ } else { // PIC
Callee = getAddrGlobal(S, DL, Ty, DAG, MipsII::MO_GOT_CALL, Chain,
FuncInfo->callPtrInfo(Sym));
IsCallReloc = true;
@@ -2848,7 +3209,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
SmallVector<SDValue, 8> Ops(1, Chain);
SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
- getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal, InternalLinkage,
+ getOpndList(Ops, RegsToPass, IsPIC, GlobalOrExternal, InternalLinkage,
IsCallReloc, CLI, Callee, Chain);
if (IsTailCall) {
@@ -2881,7 +3242,11 @@ SDValue MipsTargetLowering::LowerCallResult(
SmallVector<CCValAssign, 16> RVLocs;
MipsCCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
*DAG.getContext());
- CCInfo.AnalyzeCallResult(Ins, RetCC_Mips, CLI);
+
+ const ExternalSymbolSDNode *ES =
+ dyn_cast_or_null<const ExternalSymbolSDNode>(CLI.Callee.getNode());
+ CCInfo.AnalyzeCallResult(Ins, RetCC_Mips, CLI.RetTy,
+ ES ? ES->getSymbol() : nullptr);
// Copy all of the result registers out of their specified physreg.
for (unsigned i = 0; i != RVLocs.size(); ++i) {
@@ -3683,7 +4048,9 @@ bool MipsTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const {
}
unsigned MipsTargetLowering::getJumpTableEncoding() const {
- if (ABI.IsN64())
+
+ // FIXME: For space reasons this should be: EK_GPRel32BlockAddress.
+ if (ABI.IsN64() && isPositionIndependent())
return MachineJumpTableInfo::EK_GPRel64BlockAddress;
return TargetLowering::getJumpTableEncoding();
diff --git a/contrib/llvm/lib/Target/Mips/MipsISelLowering.h b/contrib/llvm/lib/Target/Mips/MipsISelLowering.h
index cddf090..0e47ed3 100644
--- a/contrib/llvm/lib/Target/Mips/MipsISelLowering.h
+++ b/contrib/llvm/lib/Target/Mips/MipsISelLowering.h
@@ -37,14 +37,23 @@ namespace llvm {
// Tail call
TailCall,
- // Get the Higher 16 bits from a 32-bit immediate
+ // Get the Highest (63-48) 16 bits from a 64-bit immediate
+ Highest,
+
+ // Get the Higher (47-32) 16 bits from a 64-bit immediate
+ Higher,
+
+ // Get the High 16 bits from a 32/64-bit immediate
// No relation with Mips Hi register
Hi,
- // Get the Lower 16 bits from a 32-bit immediate
+ // Get the Lower 16 bits from a 32/64-bit immediate
// No relation with Mips Lo register
Lo,
+ // Get the High 16 bits from a 32 bit immediate for accessing the GOT.
+ GotHi,
+
// Handle gp_rel (small data/bss sections) relocation.
GPRel,
@@ -107,6 +116,7 @@ namespace llvm {
Ext,
Ins,
+ CIns,
// EXTR.W instrinsic nodes.
EXTP,
@@ -238,6 +248,33 @@ namespace llvm {
bool isCheapToSpeculateCttz() const override;
bool isCheapToSpeculateCtlz() const override;
+ /// Return the register type for a given MVT, ensuring vectors are treated
+ /// as a series of gpr sized integers.
+ virtual MVT getRegisterTypeForCallingConv(MVT VT) const override;
+
+ /// Return the register type for a given MVT, ensuring vectors are treated
+ /// as a series of gpr sized integers.
+ virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context,
+ EVT VT) const override;
+
+ /// Return the number of registers for a given MVT, ensuring vectors are
+ /// treated as a series of gpr sized integers.
+ virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context,
+ EVT VT) const override;
+
+ /// Break down vectors to the correct number of gpr sized integers.
+ virtual unsigned getVectorTypeBreakdownForCallingConv(
+ LLVMContext &Context, EVT VT, EVT &IntermediateVT,
+ unsigned &NumIntermediates, MVT &RegisterVT) const override;
+
+ /// Return the correct alignment for the current calling convention.
+ virtual unsigned
+ getABIAlignmentForCallingConv(Type *ArgTy, DataLayout DL) const override {
+ if (ArgTy->isVectorTy())
+ return std::min(DL.getABITypeAlignment(ArgTy), 8U);
+ return DL.getABITypeAlignment(ArgTy);
+ }
+
ISD::NodeType getExtendForAtomicOps() const override {
return ISD::SIGN_EXTEND;
}
@@ -297,7 +334,7 @@ namespace llvm {
}
bool isJumpTableRelative() const override {
- return getTargetMachine().isPositionIndependent() || ABI.IsN64();
+ return getTargetMachine().isPositionIndependent();
}
protected:
@@ -344,8 +381,8 @@ namespace llvm {
SelectionDAG &DAG, unsigned HiFlag,
unsigned LoFlag, SDValue Chain,
const MachinePointerInfo &PtrInfo) const {
- SDValue Hi =
- DAG.getNode(MipsISD::Hi, DL, Ty, getTargetNode(N, Ty, DAG, HiFlag));
+ SDValue Hi = DAG.getNode(MipsISD::GotHi, DL, Ty,
+ getTargetNode(N, Ty, DAG, HiFlag));
Hi = DAG.getNode(ISD::ADD, DL, Ty, Hi, getGlobalReg(DAG, Ty));
SDValue Wrapper = DAG.getNode(MipsISD::Wrapper, DL, Ty, Hi,
getTargetNode(N, Ty, DAG, LoFlag));
@@ -356,6 +393,8 @@ namespace llvm {
// computing a symbol's address in non-PIC mode:
//
// (add %hi(sym), %lo(sym))
+ //
+ // This method covers O32, N32 and N64 in sym32 mode.
template <class NodeTy>
SDValue getAddrNonPIC(NodeTy *N, const SDLoc &DL, EVT Ty,
SelectionDAG &DAG) const {
@@ -364,7 +403,37 @@ namespace llvm {
return DAG.getNode(ISD::ADD, DL, Ty,
DAG.getNode(MipsISD::Hi, DL, Ty, Hi),
DAG.getNode(MipsISD::Lo, DL, Ty, Lo));
- }
+ }
+
+ // This method creates the following nodes, which are necessary for
+ // computing a symbol's address in non-PIC mode for N64.
+ //
+ // (add (shl (add (shl (add %highest(sym), %higher(sim)), 16), %high(sym)),
+ // 16), %lo(%sym))
+ //
+ // FIXME: This method is not efficent for (micro)MIPS64R6.
+ template <class NodeTy>
+ SDValue getAddrNonPICSym64(NodeTy *N, const SDLoc &DL, EVT Ty,
+ SelectionDAG &DAG) const {
+ SDValue Hi = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_HI);
+ SDValue Lo = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_LO);
+
+ SDValue Highest =
+ DAG.getNode(MipsISD::Highest, DL, Ty,
+ getTargetNode(N, Ty, DAG, MipsII::MO_HIGHEST));
+ SDValue Higher = getTargetNode(N, Ty, DAG, MipsII::MO_HIGHER);
+ SDValue HigherPart =
+ DAG.getNode(ISD::ADD, DL, Ty, Highest,
+ DAG.getNode(MipsISD::Higher, DL, Ty, Higher));
+ SDValue Cst = DAG.getConstant(16, DL, MVT::i32);
+ SDValue Shift = DAG.getNode(ISD::SHL, DL, Ty, HigherPart, Cst);
+ SDValue Add = DAG.getNode(ISD::ADD, DL, Ty, Shift,
+ DAG.getNode(MipsISD::Hi, DL, Ty, Hi));
+ SDValue Shift2 = DAG.getNode(ISD::SHL, DL, Ty, Add, Cst);
+
+ return DAG.getNode(ISD::ADD, DL, Ty, Shift2,
+ DAG.getNode(MipsISD::Lo, DL, Ty, Lo));
+ }
// This method creates the following nodes, which are necessary for
// computing a symbol's address using gp-relative addressing:
diff --git a/contrib/llvm/lib/Target/Mips/MipsInstrFPU.td b/contrib/llvm/lib/Target/Mips/MipsInstrFPU.td
index df42d56..0333fe6 100644
--- a/contrib/llvm/lib/Target/Mips/MipsInstrFPU.td
+++ b/contrib/llvm/lib/Target/Mips/MipsInstrFPU.td
@@ -443,8 +443,17 @@ let AdditionalPredicates = [NotInMicroMips] in {
}
def MFC1 : MMRel, MFC1_FT<"mfc1", GPR32Opnd, FGR32Opnd, II_MFC1,
bitconvert>, MFC1_FM<0>;
+def MFC1_D64 : MFC1_FT<"mfc1", GPR32Opnd, FGR64Opnd, II_MFC1>, MFC1_FM<0>,
+ FGR_64 {
+ let DecoderNamespace = "Mips64";
+}
def MTC1 : MMRel, MTC1_FT<"mtc1", FGR32Opnd, GPR32Opnd, II_MTC1,
bitconvert>, MFC1_FM<4>;
+def MTC1_D64 : MTC1_FT<"mtc1", FGR64Opnd, GPR32Opnd, II_MTC1>, MFC1_FM<4>,
+ FGR_64 {
+ let DecoderNamespace = "Mips64";
+}
+
let AdditionalPredicates = [NotInMicroMips] in {
def MFHC1_D32 : MMRel, MFC1_FT<"mfhc1", GPR32Opnd, AFGR64Opnd, II_MFHC1>,
MFC1_FM<3>, ISA_MIPS32R2, FGR_32;
@@ -557,11 +566,11 @@ def FSUB_S : MMRel, ADDS_FT<"sub.s", FGR32Opnd, II_SUB_S, 0, fsub>,
defm FSUB : ADDS_M<"sub.d", II_SUB_D, 0, fsub>, ADDS_FM<0x01, 17>;
def MADD_S : MMRel, MADDS_FT<"madd.s", FGR32Opnd, II_MADD_S, fadd>,
- MADDS_FM<4, 0>, INSN_MIPS4_32R2_NOT_32R6_64R6;
+ MADDS_FM<4, 0>, INSN_MIPS4_32R2_NOT_32R6_64R6, MADD4;
def MSUB_S : MMRel, MADDS_FT<"msub.s", FGR32Opnd, II_MSUB_S, fsub>,
- MADDS_FM<5, 0>, INSN_MIPS4_32R2_NOT_32R6_64R6;
+ MADDS_FM<5, 0>, INSN_MIPS4_32R2_NOT_32R6_64R6, MADD4;
-let AdditionalPredicates = [NoNaNsFPMath] in {
+let AdditionalPredicates = [NoNaNsFPMath, HasMadd4] in {
def NMADD_S : MMRel, NMADDS_FT<"nmadd.s", FGR32Opnd, II_NMADD_S, fadd>,
MADDS_FM<6, 0>, INSN_MIPS4_32R2_NOT_32R6_64R6;
def NMSUB_S : MMRel, NMADDS_FT<"nmsub.s", FGR32Opnd, II_NMSUB_S, fsub>,
@@ -569,11 +578,11 @@ let AdditionalPredicates = [NoNaNsFPMath] in {
}
def MADD_D32 : MMRel, MADDS_FT<"madd.d", AFGR64Opnd, II_MADD_D, fadd>,
- MADDS_FM<4, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_32;
+ MADDS_FM<4, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_32, MADD4;
def MSUB_D32 : MMRel, MADDS_FT<"msub.d", AFGR64Opnd, II_MSUB_D, fsub>,
- MADDS_FM<5, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_32;
+ MADDS_FM<5, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_32, MADD4;
-let AdditionalPredicates = [NoNaNsFPMath] in {
+let AdditionalPredicates = [NoNaNsFPMath, HasMadd4] in {
def NMADD_D32 : MMRel, NMADDS_FT<"nmadd.d", AFGR64Opnd, II_NMADD_D, fadd>,
MADDS_FM<6, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_32;
def NMSUB_D32 : MMRel, NMADDS_FT<"nmsub.d", AFGR64Opnd, II_NMSUB_D, fsub>,
@@ -582,12 +591,12 @@ let AdditionalPredicates = [NoNaNsFPMath] in {
let DecoderNamespace = "Mips64" in {
def MADD_D64 : MADDS_FT<"madd.d", FGR64Opnd, II_MADD_D, fadd>,
- MADDS_FM<4, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_64;
+ MADDS_FM<4, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_64, MADD4;
def MSUB_D64 : MADDS_FT<"msub.d", FGR64Opnd, II_MSUB_D, fsub>,
- MADDS_FM<5, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_64;
+ MADDS_FM<5, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_64, MADD4;
}
-let AdditionalPredicates = [NoNaNsFPMath],
+let AdditionalPredicates = [NoNaNsFPMath, HasMadd4],
DecoderNamespace = "Mips64" in {
def NMADD_D64 : NMADDS_FT<"nmadd.d", FGR64Opnd, II_NMADD_D, fadd>,
MADDS_FM<6, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_64;
@@ -681,6 +690,29 @@ def PseudoTRUNC_W_D : MipsAsmPseudoInst<(outs FGR32Opnd:$fd),
"trunc.w.d\t$fd, $fs, $rs">,
FGR_64, HARDFLOAT;
+def LoadImmSingleGPR : MipsAsmPseudoInst<(outs GPR32Opnd:$rd),
+ (ins imm64:$fpimm),
+ "li.s\t$rd, $fpimm">;
+
+def LoadImmSingleFGR : MipsAsmPseudoInst<(outs StrictlyFGR32Opnd:$rd),
+ (ins imm64:$fpimm),
+ "li.s\t$rd, $fpimm">,
+ HARDFLOAT;
+
+def LoadImmDoubleGPR : MipsAsmPseudoInst<(outs GPR32Opnd:$rd),
+ (ins imm64:$fpimm),
+ "li.d\t$rd, $fpimm">;
+
+def LoadImmDoubleFGR_32 : MipsAsmPseudoInst<(outs StrictlyAFGR64Opnd:$rd),
+ (ins imm64:$fpimm),
+ "li.d\t$rd, $fpimm">,
+ FGR_32, HARDFLOAT;
+
+def LoadImmDoubleFGR : MipsAsmPseudoInst<(outs StrictlyFGR64Opnd:$rd),
+ (ins imm64:$fpimm),
+ "li.d\t$rd, $fpimm">,
+ FGR_64, HARDFLOAT;
+
//===----------------------------------------------------------------------===//
// InstAliases.
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/lib/Target/Mips/MipsInstrInfo.cpp b/contrib/llvm/lib/Target/Mips/MipsInstrInfo.cpp
index 19af191..4adf77f 100644
--- a/contrib/llvm/lib/Target/Mips/MipsInstrInfo.cpp
+++ b/contrib/llvm/lib/Target/Mips/MipsInstrInfo.cpp
@@ -103,12 +103,9 @@ void MipsInstrInfo::BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
MachineInstrBuilder MIB = BuildMI(&MBB, DL, MCID);
for (unsigned i = 1; i < Cond.size(); ++i) {
- if (Cond[i].isReg())
- MIB.addReg(Cond[i].getReg());
- else if (Cond[i].isImm())
- MIB.addImm(Cond[i].getImm());
- else
- assert(false && "Cannot copy operand");
+ assert((Cond[i].isImm() || Cond[i].isReg()) &&
+ "Cannot copy operand for conditional branch!");
+ MIB.add(Cond[i]);
}
MIB.addMBB(TBB);
}
@@ -482,7 +479,7 @@ MipsInstrInfo::genInstrWithNewOpc(unsigned NewOpc,
MIB->RemoveOperand(0);
for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) {
- MIB.addOperand(I->getOperand(J));
+ MIB.add(I->getOperand(J));
}
MIB.addImm(0);
@@ -492,7 +489,7 @@ MipsInstrInfo::genInstrWithNewOpc(unsigned NewOpc,
if (BranchWithZeroOperand && (unsigned)ZeroOperandPosition == J)
continue;
- MIB.addOperand(I->getOperand(J));
+ MIB.add(I->getOperand(J));
}
}
@@ -501,3 +498,31 @@ MipsInstrInfo::genInstrWithNewOpc(unsigned NewOpc,
MIB.setMemRefs(I->memoperands_begin(), I->memoperands_end());
return MIB;
}
+
+bool MipsInstrInfo::findCommutedOpIndices(MachineInstr &MI, unsigned &SrcOpIdx1,
+ unsigned &SrcOpIdx2) const {
+ assert(!MI.isBundle() &&
+ "TargetInstrInfo::findCommutedOpIndices() can't handle bundles");
+
+ const MCInstrDesc &MCID = MI.getDesc();
+ if (!MCID.isCommutable())
+ return false;
+
+ switch (MI.getOpcode()) {
+ case Mips::DPADD_U_H:
+ case Mips::DPADD_U_W:
+ case Mips::DPADD_U_D:
+ case Mips::DPADD_S_H:
+ case Mips::DPADD_S_W:
+ case Mips::DPADD_S_D: {
+ // The first operand is both input and output, so it should not commute
+ if (!fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 2, 3))
+ return false;
+
+ if (!MI.getOperand(SrcOpIdx1).isReg() || !MI.getOperand(SrcOpIdx2).isReg())
+ return false;
+ return true;
+ }
+ }
+ return TargetInstrInfo::findCommutedOpIndices(MI, SrcOpIdx1, SrcOpIdx2);
+}
diff --git a/contrib/llvm/lib/Target/Mips/MipsInstrInfo.h b/contrib/llvm/lib/Target/Mips/MipsInstrInfo.h
index 347b918..45d700d 100644
--- a/contrib/llvm/lib/Target/Mips/MipsInstrInfo.h
+++ b/contrib/llvm/lib/Target/Mips/MipsInstrInfo.h
@@ -135,6 +135,9 @@ public:
MachineInstrBuilder genInstrWithNewOpc(unsigned NewOpc,
MachineBasicBlock::iterator I) const;
+ bool findCommutedOpIndices(MachineInstr &MI, unsigned &SrcOpIdx1,
+ unsigned &SrcOpIdx2) const override;
+
protected:
bool isZeroImm(const MachineOperand &op) const;
diff --git a/contrib/llvm/lib/Target/Mips/MipsInstrInfo.td b/contrib/llvm/lib/Target/Mips/MipsInstrInfo.td
index 5bc4833..89a5854 100644
--- a/contrib/llvm/lib/Target/Mips/MipsInstrInfo.td
+++ b/contrib/llvm/lib/Target/Mips/MipsInstrInfo.td
@@ -21,7 +21,7 @@ def SDT_MipsCMov : SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>,
SDTCisSameAs<1, 2>,
SDTCisSameAs<3, 4>,
SDTCisInt<4>]>;
-def SDT_MipsCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>;
+def SDT_MipsCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
def SDT_MipsCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
def SDT_MFLOHI : SDTypeProfile<1, 1, [SDTCisInt<0>, SDTCisVT<1, untyped>]>;
def SDT_MTLOHI : SDTypeProfile<1, 2, [SDTCisVT<0, untyped>,
@@ -59,10 +59,20 @@ def MipsTailCall : SDNode<"MipsISD::TailCall", SDT_MipsJmpLink,
// Hi and Lo nodes are used to handle global addresses. Used on
// MipsISelLowering to lower stuff like GlobalAddress, ExternalSymbol
// static model. (nothing to do with Mips Registers Hi and Lo)
+
+// Hi is the odd node out, on MIPS64 it can expand to either daddiu when
+// using static relocations with 64 bit symbols, or lui when using 32 bit
+// symbols.
+def MipsHigher : SDNode<"MipsISD::Higher", SDTIntUnaryOp>;
+def MipsHighest : SDNode<"MipsISD::Highest", SDTIntUnaryOp>;
def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp>;
def MipsLo : SDNode<"MipsISD::Lo", SDTIntUnaryOp>;
+
def MipsGPRel : SDNode<"MipsISD::GPRel", SDTIntUnaryOp>;
+// Hi node for accessing the GOT.
+def MipsGotHi : SDNode<"MipsISD::GotHi", SDTIntUnaryOp>;
+
// TlsGd node is used to handle General Dynamic TLS
def MipsTlsGd : SDNode<"MipsISD::TlsGd", SDTIntUnaryOp>;
@@ -128,6 +138,7 @@ def MipsSync : SDNode<"MipsISD::Sync", SDT_Sync, [SDNPHasChain,SDNPSideEffect]>;
def MipsExt : SDNode<"MipsISD::Ext", SDT_Ext>;
def MipsIns : SDNode<"MipsISD::Ins", SDT_Ins>;
+def MipsCIns : SDNode<"MipsISD::CIns", SDT_Ext>;
def MipsLWL : SDNode<"MipsISD::LWL", SDTMipsLoadLR,
[SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
@@ -205,6 +216,10 @@ def HasCnMips : Predicate<"Subtarget->hasCnMips()">,
AssemblerPredicate<"FeatureCnMips">;
def NotCnMips : Predicate<"!Subtarget->hasCnMips()">,
AssemblerPredicate<"!FeatureCnMips">;
+def IsSym32 : Predicate<"Subtarget->HasSym32()">,
+ AssemblerPredicate<"FeatureSym32">;
+def IsSym64 : Predicate<"!Subtarget->HasSym32()">,
+ AssemblerPredicate<"!FeatureSym32">;
def RelocNotPIC : Predicate<"!TM.isPositionIndependent()">;
def RelocPIC : Predicate<"TM.isPositionIndependent()">;
def NoNaNsFPMath : Predicate<"TM.Options.NoNaNsFPMath">;
@@ -223,7 +238,10 @@ def HasEVA : Predicate<"Subtarget->hasEVA()">,
AssemblerPredicate<"FeatureEVA,FeatureMips32r2">;
def HasMSA : Predicate<"Subtarget->hasMSA()">,
AssemblerPredicate<"FeatureMSA">;
-
+def HasMadd4 : Predicate<"!Subtarget->disableMadd4()">,
+ AssemblerPredicate<"!FeatureMadd4">;
+def HasMT : Predicate<"Subtarget->hasMT()">,
+ AssemblerPredicate<"FeatureMT">;
//===----------------------------------------------------------------------===//
// Mips GPR size adjectives.
@@ -237,6 +255,14 @@ class PTR_32 { list<Predicate> PTRPredicates = [IsPTR32bit]; }
class PTR_64 { list<Predicate> PTRPredicates = [IsPTR64bit]; }
//===----------------------------------------------------------------------===//
+// Mips Symbol size adjectives.
+// They are mutally exculsive.
+//===----------------------------------------------------------------------===//
+
+class SYM_32 { list<Predicate> SYMPredicates = [IsSym32]; }
+class SYM_64 { list<Predicate> SYMPredicates = [IsSym64]; }
+
+//===----------------------------------------------------------------------===//
// Mips ISA/ASE membership and instruction group membership adjectives.
// They are mutually exclusive.
//===----------------------------------------------------------------------===//
@@ -357,6 +383,10 @@ class ASE_MSA64 {
list<Predicate> InsnPredicates = [HasMSA, HasMips64];
}
+class ASE_MT {
+ list <Predicate> InsnPredicates = [HasMT];
+}
+
// Class used for separating microMIPSr6 and microMIPS (r3) instruction.
// It can be used only on instructions that doesn't inherit PredicateControl.
class ISA_MICROMIPS_NOT_32R6_64R6 : PredicateControl {
@@ -367,6 +397,10 @@ class ASE_NOT_DSP {
list<Predicate> InsnPredicates = [NotDSP];
}
+class MADD4 {
+ list<Predicate> AdditionalPredicates = [HasMadd4];
+}
+
//===----------------------------------------------------------------------===//
class MipsPat<dag pattern, dag result> : Pat<pattern, result>, PredicateControl {
@@ -519,7 +553,7 @@ def UImm32CoercedAsmOperandClass : UImmAnyAsmOperandClass<33, []> {
def SImm32RelaxedAsmOperandClass
: SImmAsmOperandClass<32, [UImm32CoercedAsmOperandClass]> {
let Name = "SImm32_Relaxed";
- let PredicateMethod = "isAnyImm<32>";
+ let PredicateMethod = "isAnyImm<33>";
let DiagnosticType = "SImm32_Relaxed";
}
def SImm32AsmOperandClass
@@ -1150,6 +1184,10 @@ def immZExt5Plus33 : PatLeaf<(imm), [{
return isUInt<5>(N->getZExtValue() - 33);
}]>;
+def immZExt5To31 : SDNodeXForm<imm, [{
+ return getImm(N, 31 - N->getZExtValue());
+}]>;
+
// True if (N + 1) fits in 16-bit field.
def immSExt16Plus1 : PatLeaf<(imm), [{
return isInt<17>(N->getSExtValue()) && isInt<16>(N->getSExtValue() + 1);
@@ -1692,8 +1730,8 @@ let isReturn=1, isTerminator=1, isBarrier=1, hasCtrlDep=1, isCTI=1 in {
}
let Defs = [SP], Uses = [SP], hasSideEffects = 1 in {
-def ADJCALLSTACKDOWN : MipsPseudo<(outs), (ins i32imm:$amt),
- [(callseq_start timm:$amt)]>;
+def ADJCALLSTACKDOWN : MipsPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
+ [(callseq_start timm:$amt1, timm:$amt2)]>;
def ADJCALLSTACKUP : MipsPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
[(callseq_end timm:$amt1, timm:$amt2)]>;
}
@@ -2281,9 +2319,38 @@ def SEQIMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd),
def : MipsInstAlias<"seq $rd, $imm",
(SEQIMacro GPR32Opnd:$rd, GPR32Opnd:$rd, simm32:$imm), 0>,
NOT_ASE_CNMIPS;
+
+def MULImmMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rd, GPR32Opnd:$rs,
+ simm32_relaxed:$imm),
+ "mul\t$rd, $rs, $imm">,
+ ISA_MIPS1_NOT_32R6_64R6;
+def MULOMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rd, GPR32Opnd:$rs,
+ GPR32Opnd:$rt),
+ "mulo\t$rd, $rs, $rt">,
+ ISA_MIPS1_NOT_32R6_64R6;
+def MULOUMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rd, GPR32Opnd:$rs,
+ GPR32Opnd:$rt),
+ "mulou\t$rd, $rs, $rt">,
+ ISA_MIPS1_NOT_32R6_64R6;
+
//===----------------------------------------------------------------------===//
// Instruction aliases
//===----------------------------------------------------------------------===//
+
+multiclass OneOrTwoOperandMacroImmediateAlias<string Memnomic,
+ Instruction Opcode,
+ RegisterOperand RO = GPR32Opnd,
+ Operand Imm = simm32_relaxed> {
+ def : MipsInstAlias<!strconcat(Memnomic, " $rs, $rt, $imm"),
+ (Opcode RO:$rs,
+ RO:$rt,
+ Imm:$imm), 0>;
+ def : MipsInstAlias<!strconcat(Memnomic, " $rs, $imm"),
+ (Opcode RO:$rs,
+ RO:$rs,
+ Imm:$imm), 0>;
+}
+
def : MipsInstAlias<"move $dst, $src",
(OR GPR32Opnd:$dst, GPR32Opnd:$src, ZERO), 1>,
GPR_32 {
@@ -2296,26 +2363,7 @@ def : MipsInstAlias<"move $dst, $src",
}
def : MipsInstAlias<"bal $offset", (BGEZAL ZERO, brtarget:$offset), 0>,
ISA_MIPS1_NOT_32R6_64R6;
-def : MipsInstAlias<
- "addu $rs, $rt, $imm",
- (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rt, simm32_relaxed:$imm), 0>;
-def : MipsInstAlias<
- "addu $rs, $imm",
- (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rs, simm32_relaxed:$imm), 0>;
-def : MipsInstAlias<
- "add $rs, $rt, $imm",
- (ADDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm32_relaxed:$imm), 0>,
- ISA_MIPS1_NOT_32R6_64R6;
-def : MipsInstAlias<
- "add $rs, $imm",
- (ADDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm32_relaxed:$imm), 0>,
- ISA_MIPS1_NOT_32R6_64R6;
-def : MipsInstAlias<
- "and $rs, $rt, $imm",
- (ANDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm32_relaxed:$imm), 0>;
-def : MipsInstAlias<
- "and $rs, $imm",
- (ANDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm32_relaxed:$imm), 0>;
+
def : MipsInstAlias<"j $rs", (JR GPR32Opnd:$rs), 0>;
let Predicates = [NotInMicroMips] in {
def : MipsInstAlias<"jalr $rs", (JALR RA, GPR32Opnd:$rs), 0>;
@@ -2343,36 +2391,26 @@ let AdditionalPredicates = [NotInMicroMips] in {
"sgtu $$rs, $rt",
(SLTu GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>;
def : MipsInstAlias<
- "slt $rs, $rt, $imm",
- (SLTi GPR32Opnd:$rs, GPR32Opnd:$rt, simm32_relaxed:$imm), 0>;
- def : MipsInstAlias<
- "sltu $rt, $rs, $imm",
- (SLTiu GPR32Opnd:$rt, GPR32Opnd:$rs, simm32_relaxed:$imm), 0>;
- def : MipsInstAlias<
- "and $rs, $rt, $imm",
- (ANDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm32_relaxed:$imm), 0>;
- def : MipsInstAlias<
- "and $rs, $imm",
- (ANDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm32_relaxed:$imm), 0>;
- def : MipsInstAlias<
- "xor $rs, $rt, $imm",
- (XORi GPR32Opnd:$rs, GPR32Opnd:$rt, simm32_relaxed:$imm), 0>;
- def : MipsInstAlias<
- "xor $rs, $imm",
- (XORi GPR32Opnd:$rs, GPR32Opnd:$rs, simm32_relaxed:$imm), 0>;
- def : MipsInstAlias<
- "or $rs, $rt, $imm",
- (ORi GPR32Opnd:$rs, GPR32Opnd:$rt, simm32_relaxed:$imm), 0>;
- def : MipsInstAlias<
- "or $rs, $imm",
- (ORi GPR32Opnd:$rs, GPR32Opnd:$rs, simm32_relaxed:$imm), 0>;
- def : MipsInstAlias<
"not $rt, $rs",
(NOR GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>;
def : MipsInstAlias<
"not $rt",
(NOR GPR32Opnd:$rt, GPR32Opnd:$rt, ZERO), 0>;
def : MipsInstAlias<"nop", (SLL ZERO, ZERO, 0), 1>;
+
+ defm : OneOrTwoOperandMacroImmediateAlias<"add", ADDi>, ISA_MIPS1_NOT_32R6_64R6;
+
+ defm : OneOrTwoOperandMacroImmediateAlias<"addu", ADDiu>;
+
+ defm : OneOrTwoOperandMacroImmediateAlias<"and", ANDi>, GPR_32;
+
+ defm : OneOrTwoOperandMacroImmediateAlias<"or", ORi>, GPR_32;
+
+ defm : OneOrTwoOperandMacroImmediateAlias<"xor", XORi>, GPR_32;
+
+ defm : OneOrTwoOperandMacroImmediateAlias<"slt", SLTi>, GPR_32;
+
+ defm : OneOrTwoOperandMacroImmediateAlias<"sltu", SLTiu>, GPR_32;
}
def : MipsInstAlias<"mfc0 $rt, $rd", (MFC0 GPR32Opnd:$rt, COP0Opnd:$rd, 0), 0>;
def : MipsInstAlias<"mtc0 $rt, $rd", (MTC0 COP0Opnd:$rd, GPR32Opnd:$rt, 0), 0>;
@@ -2445,6 +2483,14 @@ let AdditionalPredicates = [NotInMicroMips] in {
def : MipsInstAlias<"sdbbp", (SDBBP 0)>, ISA_MIPS32_NOT_32R6_64R6;
def : MipsInstAlias<"sync",
(SYNC 0), 1>, ISA_MIPS2;
+
+def : MipsInstAlias<"mulo $rs, $rt",
+ (MULOMacro GPR32Opnd:$rs, GPR32Opnd:$rs, GPR32Opnd:$rt), 0>,
+ ISA_MIPS1_NOT_32R6_64R6;
+def : MipsInstAlias<"mulou $rs, $rt",
+ (MULOUMacro GPR32Opnd:$rs, GPR32Opnd:$rs, GPR32Opnd:$rt), 0>,
+ ISA_MIPS1_NOT_32R6_64R6;
+
//===----------------------------------------------------------------------===//
// Assembler Pseudo Instructions
//===----------------------------------------------------------------------===//
@@ -2472,9 +2518,12 @@ def JalTwoReg : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins GPR32Opnd:$rs),
def JalOneReg : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs),
"jal\t$rs"> ;
-def NORImm : MipsAsmPseudoInst<
- (outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt, simm32:$imm),
- "nor\t$rs, $rt, $imm"> ;
+class NORIMM_DESC_BASE<RegisterOperand RO, DAGOperand Imm> :
+ MipsAsmPseudoInst<(outs RO:$rs), (ins RO:$rt, Imm:$imm),
+ "nor\t$rs, $rt, $imm">;
+def NORImm : NORIMM_DESC_BASE<GPR32Opnd, simm32_relaxed>, GPR_32;
+def : MipsInstAlias<"nor\t$rs, $imm", (NORImm GPR32Opnd:$rs, GPR32Opnd:$rs,
+ simm32_relaxed:$imm)>, GPR_32;
let hasDelaySlot = 1, isCTI = 1 in {
def BneImm : MipsAsmPseudoInst<(outs GPR32Opnd:$rt),
@@ -2512,6 +2561,9 @@ class CondBranchImmPseudo<string instr_asm> :
MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, imm64:$imm, brtarget:$offset),
!strconcat(instr_asm, "\t$rs, $imm, $offset")>;
+def BEQLImmMacro : CondBranchImmPseudo<"beql">, ISA_MIPS2_NOT_32R6_64R6;
+def BNELImmMacro : CondBranchImmPseudo<"bnel">, ISA_MIPS2_NOT_32R6_64R6;
+
def BLTImmMacro : CondBranchImmPseudo<"blt">;
def BLEImmMacro : CondBranchImmPseudo<"ble">;
def BGEImmMacro : CondBranchImmPseudo<"bge">;
@@ -2535,34 +2587,46 @@ def BGTULImmMacro : CondBranchImmPseudo<"bgtul">, ISA_MIPS2_NOT_32R6_64R6;
// Once the tablegen-erated errors are made better, this needs to be fixed and
// predicates needs to be restored.
-def SDivMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd),
+def SDivMacro : MipsAsmPseudoInst<(outs GPR32NonZeroOpnd:$rd),
(ins GPR32Opnd:$rs, GPR32Opnd:$rt),
"div\t$rd, $rs, $rt">,
ISA_MIPS1_NOT_32R6_64R6;
+def SDivIMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd),
+ (ins GPR32Opnd:$rs, simm32:$imm),
+ "div\t$rd, $rs, $imm">,
+ ISA_MIPS1_NOT_32R6_64R6;
def UDivMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd),
(ins GPR32Opnd:$rs, GPR32Opnd:$rt),
"divu\t$rd, $rs, $rt">,
ISA_MIPS1_NOT_32R6_64R6;
-def : MipsInstAlias<"div $rt, $rs", (SDivMacro GPR32Opnd:$rt, GPR32Opnd:$rt,
- GPR32Opnd:$rs), 0>,
+def UDivIMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd),
+ (ins GPR32Opnd:$rs, simm32:$imm),
+ "divu\t$rd, $rs, $imm">,
+ ISA_MIPS1_NOT_32R6_64R6;
+
+
+def : MipsInstAlias<"div $rs, $rt", (SDIV GPR32ZeroOpnd:$rs,
+ GPR32Opnd:$rt), 0>,
+ ISA_MIPS1_NOT_32R6_64R6;
+def : MipsInstAlias<"div $rs, $rt", (SDivMacro GPR32NonZeroOpnd:$rs,
+ GPR32NonZeroOpnd:$rs,
+ GPR32Opnd:$rt), 0>,
+ ISA_MIPS1_NOT_32R6_64R6;
+def : MipsInstAlias<"div $rd, $imm", (SDivIMacro GPR32Opnd:$rd, GPR32Opnd:$rd,
+ simm32:$imm), 0>,
ISA_MIPS1_NOT_32R6_64R6;
-def : MipsInstAlias<"divu $rt, $rs", (UDivMacro GPR32Opnd:$rt, GPR32Opnd:$rt,
+
+def : MipsInstAlias<"divu $rt, $rs", (UDIV GPR32ZeroOpnd:$rt,
+ GPR32Opnd:$rs), 0>,
+ ISA_MIPS1_NOT_32R6_64R6;
+def : MipsInstAlias<"divu $rt, $rs", (UDivMacro GPR32NonZeroOpnd:$rt,
+ GPR32NonZeroOpnd:$rt,
GPR32Opnd:$rs), 0>,
ISA_MIPS1_NOT_32R6_64R6;
-def DSDivMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd),
- (ins GPR32Opnd:$rs, GPR32Opnd:$rt),
- "ddiv\t$rd, $rs, $rt">,
- ISA_MIPS64_NOT_64R6;
-def DUDivMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd),
- (ins GPR32Opnd:$rs, GPR32Opnd:$rt),
- "ddivu\t$rd, $rs, $rt">,
- ISA_MIPS64_NOT_64R6;
-def : MipsInstAlias<"ddiv $rt, $rs", (DSDivMacro GPR32Opnd:$rt, GPR32Opnd:$rt,
- GPR32Opnd:$rs), 0>,
- ISA_MIPS64_NOT_64R6;
-def : MipsInstAlias<"ddivu $rt, $rs", (DUDivMacro GPR32Opnd:$rt, GPR32Opnd:$rt,
- GPR32Opnd:$rs), 0>,
- ISA_MIPS64_NOT_64R6;
+
+def : MipsInstAlias<"divu $rd, $imm", (UDivIMacro GPR32Opnd:$rd, GPR32Opnd:$rd,
+ simm32:$imm), 0>,
+ ISA_MIPS1_NOT_32R6_64R6;
def Ulh : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins mem:$addr),
"ulh\t$rt, $addr">; //, ISA_MIPS1_NOT_32R6_64R6;
@@ -2647,30 +2711,40 @@ def : MipsPat<(MipsTailCall (iPTR tglobaladdr:$dst)),
def : MipsPat<(MipsTailCall (iPTR texternalsym:$dst)),
(TAILCALL texternalsym:$dst)>;
// hi/lo relocs
-def : MipsPat<(MipsHi tglobaladdr:$in), (LUi tglobaladdr:$in)>;
-def : MipsPat<(MipsHi tblockaddress:$in), (LUi tblockaddress:$in)>;
-def : MipsPat<(MipsHi tjumptable:$in), (LUi tjumptable:$in)>;
-def : MipsPat<(MipsHi tconstpool:$in), (LUi tconstpool:$in)>;
-def : MipsPat<(MipsHi tglobaltlsaddr:$in), (LUi tglobaltlsaddr:$in)>;
-def : MipsPat<(MipsHi texternalsym:$in), (LUi texternalsym:$in)>;
-
-def : MipsPat<(MipsLo tglobaladdr:$in), (ADDiu ZERO, tglobaladdr:$in)>;
-def : MipsPat<(MipsLo tblockaddress:$in), (ADDiu ZERO, tblockaddress:$in)>;
-def : MipsPat<(MipsLo tjumptable:$in), (ADDiu ZERO, tjumptable:$in)>;
-def : MipsPat<(MipsLo tconstpool:$in), (ADDiu ZERO, tconstpool:$in)>;
-def : MipsPat<(MipsLo tglobaltlsaddr:$in), (ADDiu ZERO, tglobaltlsaddr:$in)>;
-def : MipsPat<(MipsLo texternalsym:$in), (ADDiu ZERO, texternalsym:$in)>;
-
-def : MipsPat<(add GPR32:$hi, (MipsLo tglobaladdr:$lo)),
- (ADDiu GPR32:$hi, tglobaladdr:$lo)>;
-def : MipsPat<(add GPR32:$hi, (MipsLo tblockaddress:$lo)),
- (ADDiu GPR32:$hi, tblockaddress:$lo)>;
-def : MipsPat<(add GPR32:$hi, (MipsLo tjumptable:$lo)),
- (ADDiu GPR32:$hi, tjumptable:$lo)>;
-def : MipsPat<(add GPR32:$hi, (MipsLo tconstpool:$lo)),
- (ADDiu GPR32:$hi, tconstpool:$lo)>;
-def : MipsPat<(add GPR32:$hi, (MipsLo tglobaltlsaddr:$lo)),
- (ADDiu GPR32:$hi, tglobaltlsaddr:$lo)>;
+multiclass MipsHiLoRelocs<Instruction Lui, Instruction Addiu,
+ Register ZeroReg, RegisterOperand GPROpnd> {
+ def : MipsPat<(MipsHi tglobaladdr:$in), (Lui tglobaladdr:$in)>;
+ def : MipsPat<(MipsHi tblockaddress:$in), (Lui tblockaddress:$in)>;
+ def : MipsPat<(MipsHi tjumptable:$in), (Lui tjumptable:$in)>;
+ def : MipsPat<(MipsHi tconstpool:$in), (Lui tconstpool:$in)>;
+ def : MipsPat<(MipsHi tglobaltlsaddr:$in), (Lui tglobaltlsaddr:$in)>;
+ def : MipsPat<(MipsHi texternalsym:$in), (Lui texternalsym:$in)>;
+
+ def : MipsPat<(MipsLo tglobaladdr:$in), (Addiu ZeroReg, tglobaladdr:$in)>;
+ def : MipsPat<(MipsLo tblockaddress:$in),
+ (Addiu ZeroReg, tblockaddress:$in)>;
+ def : MipsPat<(MipsLo tjumptable:$in), (Addiu ZeroReg, tjumptable:$in)>;
+ def : MipsPat<(MipsLo tconstpool:$in), (Addiu ZeroReg, tconstpool:$in)>;
+ def : MipsPat<(MipsLo tglobaltlsaddr:$in),
+ (Addiu ZeroReg, tglobaltlsaddr:$in)>;
+ def : MipsPat<(MipsLo texternalsym:$in), (Addiu ZeroReg, texternalsym:$in)>;
+
+ def : MipsPat<(add GPROpnd:$hi, (MipsLo tglobaladdr:$lo)),
+ (Addiu GPROpnd:$hi, tglobaladdr:$lo)>;
+ def : MipsPat<(add GPROpnd:$hi, (MipsLo tblockaddress:$lo)),
+ (Addiu GPROpnd:$hi, tblockaddress:$lo)>;
+ def : MipsPat<(add GPROpnd:$hi, (MipsLo tjumptable:$lo)),
+ (Addiu GPROpnd:$hi, tjumptable:$lo)>;
+ def : MipsPat<(add GPROpnd:$hi, (MipsLo tconstpool:$lo)),
+ (Addiu GPROpnd:$hi, tconstpool:$lo)>;
+ def : MipsPat<(add GPROpnd:$hi, (MipsLo tglobaltlsaddr:$lo)),
+ (Addiu GPROpnd:$hi, tglobaltlsaddr:$lo)>;
+}
+
+defm : MipsHiLoRelocs<LUi, ADDiu, ZERO, GPR32Opnd>;
+
+def : MipsPat<(MipsGotHi tglobaladdr:$in), (LUi tglobaladdr:$in)>;
+def : MipsPat<(MipsGotHi texternalsym:$in), (LUi texternalsym:$in)>;
// gp_rel relocs
def : MipsPat<(add GPR32:$gp, (MipsGPRel tglobaladdr:$in)),
@@ -2850,6 +2924,10 @@ include "MipsMSAInstrInfo.td"
include "MipsEVAInstrFormats.td"
include "MipsEVAInstrInfo.td"
+// MT
+include "MipsMTInstrFormats.td"
+include "MipsMTInstrInfo.td"
+
// Micromips
include "MicroMipsInstrFormats.td"
include "MicroMipsInstrInfo.td"
diff --git a/contrib/llvm/lib/Target/Mips/MipsLongBranch.cpp b/contrib/llvm/lib/Target/Mips/MipsLongBranch.cpp
index 1087d0e..b95f115 100644
--- a/contrib/llvm/lib/Target/Mips/MipsLongBranch.cpp
+++ b/contrib/llvm/lib/Target/Mips/MipsLongBranch.cpp
@@ -13,20 +13,31 @@
// FIXME: Fix pc-region jump instructions which cross 256MB segment boundaries.
//===----------------------------------------------------------------------===//
-#include "Mips.h"
+#include "MCTargetDesc/MipsABIInfo.h"
#include "MCTargetDesc/MipsBaseInfo.h"
#include "MCTargetDesc/MipsMCNaCl.h"
+#include "Mips.h"
+#include "MipsInstrInfo.h"
#include "MipsMachineFunction.h"
+#include "MipsSubtarget.h"
#include "MipsTargetMachine.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/IR/Function.h"
+#include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/IR/DebugLoc.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
-#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetRegisterInfo.h"
+#include <cassert>
+#include <cstdint>
+#include <iterator>
using namespace llvm;
@@ -47,24 +58,25 @@ static cl::opt<bool> ForceLongBranch(
cl::Hidden);
namespace {
+
typedef MachineBasicBlock::iterator Iter;
typedef MachineBasicBlock::reverse_iterator ReverseIter;
struct MBBInfo {
- uint64_t Size, Address;
- bool HasLongBranch;
- MachineInstr *Br;
+ uint64_t Size = 0;
+ uint64_t Address;
+ bool HasLongBranch = false;
+ MachineInstr *Br = nullptr;
- MBBInfo() : Size(0), HasLongBranch(false), Br(nullptr) {}
+ MBBInfo() = default;
};
class MipsLongBranch : public MachineFunctionPass {
-
public:
static char ID;
- MipsLongBranch(TargetMachine &tm)
- : MachineFunctionPass(ID), TM(tm), IsPIC(TM.isPositionIndependent()),
- ABI(static_cast<const MipsTargetMachine &>(TM).getABI()) {}
+
+ MipsLongBranch()
+ : MachineFunctionPass(ID), ABI(MipsABIInfo::Unknown()) {}
StringRef getPassName() const override { return "Mips Long Branch"; }
@@ -83,7 +95,6 @@ namespace {
MachineBasicBlock *MBBOpnd);
void expandToLongBranch(MBBInfo &Info);
- const TargetMachine &TM;
MachineFunction *MF;
SmallVector<MBBInfo, 16> MBBInfos;
bool IsPIC;
@@ -92,13 +103,8 @@ namespace {
};
char MipsLongBranch::ID = 0;
-} // end of anonymous namespace
-/// createMipsLongBranchPass - Returns a pass that converts branches to long
-/// branches.
-FunctionPass *llvm::createMipsLongBranchPass(MipsTargetMachine &tm) {
- return new MipsLongBranch(tm);
-}
+} // end anonymous namespace
/// Iterate over list of Br's operands and search for a MachineBasicBlock
/// operand.
@@ -461,6 +467,12 @@ bool MipsLongBranch::runOnMachineFunction(MachineFunction &F) {
static_cast<const MipsSubtarget &>(F.getSubtarget());
const MipsInstrInfo *TII =
static_cast<const MipsInstrInfo *>(STI.getInstrInfo());
+
+
+ const TargetMachine& TM = F.getTarget();
+ IsPIC = TM.isPositionIndependent();
+ ABI = static_cast<const MipsTargetMachine &>(TM).getABI();
+
LongBranchSeqSize =
!IsPIC ? 2 : (ABI.IsN64() ? 10 : (!STI.isTargetNaCl() ? 9 : 10));
@@ -530,3 +542,7 @@ bool MipsLongBranch::runOnMachineFunction(MachineFunction &F) {
return true;
}
+
+/// createMipsLongBranchPass - Returns a pass that converts branches to long
+/// branches.
+FunctionPass *llvm::createMipsLongBranchPass() { return new MipsLongBranch(); }
diff --git a/contrib/llvm/lib/Target/Mips/MipsMSAInstrInfo.td b/contrib/llvm/lib/Target/Mips/MipsMSAInstrInfo.td
index 8b04fcb..bf79f0f 100644
--- a/contrib/llvm/lib/Target/Mips/MipsMSAInstrInfo.td
+++ b/contrib/llvm/lib/Target/Mips/MipsMSAInstrInfo.td
@@ -3781,6 +3781,80 @@ let Predicates = [HasMSA] in {
ISA_MIPS1_NOT_32R6_64R6;
}
+def vsplati64_imm_eq_63 : PatLeaf<(bitconvert (v4i32 (build_vector))), [{
+ APInt Imm;
+ SDNode *BV = N->getOperand(0).getNode();
+ EVT EltTy = N->getValueType(0).getVectorElementType();
+
+ return selectVSplat(BV, Imm, EltTy.getSizeInBits()) &&
+ Imm.getBitWidth() == EltTy.getSizeInBits() && Imm == 63;
+}]>;
+
+def immi32Cst7 : ImmLeaf<i32, [{return isUInt<32>(Imm) && Imm == 7;}]>;
+def immi32Cst15 : ImmLeaf<i32, [{return isUInt<32>(Imm) && Imm == 15;}]>;
+def immi32Cst31 : ImmLeaf<i32, [{return isUInt<32>(Imm) && Imm == 31;}]>;
+
+def vsplati8imm7 : PatFrag<(ops node:$wt),
+ (and node:$wt, (vsplati8 immi32Cst7))>;
+def vsplati16imm15 : PatFrag<(ops node:$wt),
+ (and node:$wt, (vsplati16 immi32Cst15))>;
+def vsplati32imm31 : PatFrag<(ops node:$wt),
+ (and node:$wt, (vsplati32 immi32Cst31))>;
+def vsplati64imm63 : PatFrag<(ops node:$wt),
+ (and node:$wt, vsplati64_imm_eq_63)>;
+
+class MSAShiftPat<SDNode Node, ValueType VT, MSAInst Insn, dag Vec> :
+ MSAPat<(VT (Node VT:$ws, (VT (and VT:$wt, Vec)))),
+ (VT (Insn VT:$ws, VT:$wt))>;
+
+class MSABitPat<SDNode Node, ValueType VT, MSAInst Insn, PatFrag Frag> :
+ MSAPat<(VT (Node VT:$ws, (shl vsplat_imm_eq_1, (Frag VT:$wt)))),
+ (VT (Insn VT:$ws, VT:$wt))>;
+
+multiclass MSAShiftPats<SDNode Node, string Insn> {
+ def : MSAShiftPat<Node, v16i8, !cast<MSAInst>(Insn#_B),
+ (vsplati8 immi32Cst7)>;
+ def : MSAShiftPat<Node, v8i16, !cast<MSAInst>(Insn#_H),
+ (vsplati16 immi32Cst15)>;
+ def : MSAShiftPat<Node, v4i32, !cast<MSAInst>(Insn#_W),
+ (vsplati32 immi32Cst31)>;
+ def : MSAPat<(v2i64 (Node v2i64:$ws, (v2i64 (and v2i64:$wt,
+ vsplati64_imm_eq_63)))),
+ (v2i64 (!cast<MSAInst>(Insn#_D) v2i64:$ws, v2i64:$wt))>;
+}
+
+multiclass MSABitPats<SDNode Node, string Insn> {
+ def : MSABitPat<Node, v16i8, !cast<MSAInst>(Insn#_B), vsplati8imm7>;
+ def : MSABitPat<Node, v8i16, !cast<MSAInst>(Insn#_H), vsplati16imm15>;
+ def : MSABitPat<Node, v4i32, !cast<MSAInst>(Insn#_W), vsplati32imm31>;
+ def : MSAPat<(Node v2i64:$ws, (shl (v2i64 vsplati64_imm_eq_1),
+ (vsplati64imm63 v2i64:$wt))),
+ (v2i64 (!cast<MSAInst>(Insn#_D) v2i64:$ws, v2i64:$wt))>;
+}
+
+defm : MSAShiftPats<shl, "SLL">;
+defm : MSAShiftPats<srl, "SRL">;
+defm : MSAShiftPats<sra, "SRA">;
+defm : MSABitPats<xor, "BNEG">;
+defm : MSABitPats<or, "BSET">;
+
+def : MSAPat<(and v16i8:$ws, (xor (shl vsplat_imm_eq_1,
+ (vsplati8imm7 v16i8:$wt)),
+ immAllOnesV)),
+ (v16i8 (BCLR_B v16i8:$ws, v16i8:$wt))>;
+def : MSAPat<(and v8i16:$ws, (xor (shl vsplat_imm_eq_1,
+ (vsplati16imm15 v8i16:$wt)),
+ immAllOnesV)),
+ (v8i16 (BCLR_H v8i16:$ws, v8i16:$wt))>;
+def : MSAPat<(and v4i32:$ws, (xor (shl vsplat_imm_eq_1,
+ (vsplati32imm31 v4i32:$wt)),
+ immAllOnesV)),
+ (v4i32 (BCLR_W v4i32:$ws, v4i32:$wt))>;
+def : MSAPat<(and v2i64:$ws, (xor (shl (v2i64 vsplati64_imm_eq_1),
+ (vsplati64imm63 v2i64:$wt)),
+ (bitconvert (v4i32 immAllOnesV)))),
+ (v2i64 (BCLR_D v2i64:$ws, v2i64:$wt))>;
+
// Vector extraction with fixed index.
//
// Extracting 32-bit values on MSA32 should always use COPY_S_W rather than
diff --git a/contrib/llvm/lib/Target/Mips/MipsMTInstrFormats.td b/contrib/llvm/lib/Target/Mips/MipsMTInstrFormats.td
new file mode 100644
index 0000000..64bee5b
--- /dev/null
+++ b/contrib/llvm/lib/Target/Mips/MipsMTInstrFormats.td
@@ -0,0 +1,78 @@
+//===-- 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.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Describe the MIPS MT instructions format
+//
+// opcode - operation code.
+// rt - destination register
+//
+//===----------------------------------------------------------------------===//
+
+class MipsMTInst : MipsInst<(outs), (ins), "", [], NoItinerary, FrmOther>,
+ PredicateControl {
+ let DecoderNamespace = "Mips";
+ let EncodingPredicates = [HasStdEnc];
+}
+
+class OPCODE1<bits<1> Val> {
+ bits<1> Value = Val;
+}
+
+def OPCODE_SC_D : OPCODE1<0b0>;
+def OPCODE_SC_E : OPCODE1<0b1>;
+
+class FIELD5<bits<5> Val> {
+ bits<5> Value = Val;
+}
+
+def FIELD5_1_DMT_EMT : FIELD5<0b00001>;
+def FIELD5_2_DMT_EMT : FIELD5<0b01111>;
+def FIELD5_1_2_DVPE_EVPE : FIELD5<0b00000>;
+
+class COP0_MFMC0_MT<FIELD5 Op1, FIELD5 Op2, OPCODE1 sc> : MipsMTInst {
+ bits<32> Inst;
+
+ bits<5> rt;
+ let Inst{31-26} = 0b010000; // COP0
+ let Inst{25-21} = 0b01011; // MFMC0
+ let Inst{20-16} = rt;
+ let Inst{15-11} = Op1.Value;
+ let Inst{10-6} = Op2.Value;
+ let Inst{5} = sc.Value;
+ let Inst{4-3} = 0b00;
+ let Inst{2-0} = 0b001;
+}
+
+class SPECIAL3_MT_FORK : MipsMTInst {
+ bits<32> Inst;
+
+ bits<5> rs;
+ bits<5> rt;
+ bits<5> rd;
+ let Inst{31-26} = 0b011111; // SPECIAL3
+ let Inst{25-21} = rs;
+ let Inst{20-16} = rt;
+ let Inst{15-11} = rd;
+ let Inst{10-6} = 0b00000;
+ let Inst{5-0} = 0b001000; // FORK
+}
+
+class SPECIAL3_MT_YIELD : MipsMTInst {
+ bits<32> Inst;
+
+ bits<5> rs;
+ bits<5> rd;
+ let Inst{31-26} = 0b011111; // SPECIAL3
+ let Inst{25-21} = rs;
+ let Inst{20-16} = 0b00000;
+ let Inst{15-11} = rd;
+ let Inst{10-6} = 0b00000;
+ let Inst{5-0} = 0b001001; // FORK
+}
diff --git a/contrib/llvm/lib/Target/Mips/MipsMTInstrInfo.td b/contrib/llvm/lib/Target/Mips/MipsMTInstrInfo.td
new file mode 100644
index 0000000..ab6693f
--- /dev/null
+++ b/contrib/llvm/lib/Target/Mips/MipsMTInstrInfo.td
@@ -0,0 +1,98 @@
+//===-- 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.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// MIPS MT Instruction Encodings
+//===----------------------------------------------------------------------===//
+
+class DMT_ENC : COP0_MFMC0_MT<FIELD5_1_DMT_EMT, FIELD5_2_DMT_EMT,
+ OPCODE_SC_D>;
+
+class EMT_ENC : COP0_MFMC0_MT<FIELD5_1_DMT_EMT, FIELD5_2_DMT_EMT,
+ OPCODE_SC_E>;
+
+class DVPE_ENC : COP0_MFMC0_MT<FIELD5_1_2_DVPE_EVPE, FIELD5_1_2_DVPE_EVPE,
+ OPCODE_SC_D>;
+
+class EVPE_ENC : COP0_MFMC0_MT<FIELD5_1_2_DVPE_EVPE, FIELD5_1_2_DVPE_EVPE,
+ OPCODE_SC_E>;
+
+class FORK_ENC : SPECIAL3_MT_FORK;
+
+class YIELD_ENC : SPECIAL3_MT_YIELD;
+
+//===----------------------------------------------------------------------===//
+// MIPS MT Instruction Descriptions
+//===----------------------------------------------------------------------===//
+
+class MT_1R_DESC_BASE<string instr_asm, InstrItinClass Itin = NoItinerary> {
+ dag OutOperandList = (outs GPR32Opnd:$rt);
+ dag InOperandList = (ins);
+ string AsmString = !strconcat(instr_asm, "\t$rt");
+ list<dag> Pattern = [];
+ InstrItinClass Itinerary = Itin;
+}
+
+class FORK_DESC {
+ dag OutOperandList = (outs GPR32Opnd:$rs, GPR32Opnd:$rd);
+ dag InOperandList = (ins GPR32Opnd:$rt);
+ string AsmString = "fork\t$rd, $rs, $rt";
+ list<dag> Pattern = [];
+ InstrItinClass Itinerary = II_FORK;
+}
+
+class YIELD_DESC {
+ dag OutOperandList = (outs GPR32Opnd:$rd);
+ dag InOperandList = (ins GPR32Opnd:$rs);
+ string AsmString = "yield\t$rd, $rs";
+ list<dag> Pattern = [];
+ InstrItinClass Itinerary = II_YIELD;
+}
+
+class DMT_DESC : MT_1R_DESC_BASE<"dmt", II_DMT>;
+
+class EMT_DESC : MT_1R_DESC_BASE<"emt", II_EMT>;
+
+class DVPE_DESC : MT_1R_DESC_BASE<"dvpe", II_DVPE>;
+
+class EVPE_DESC : MT_1R_DESC_BASE<"evpe", II_EVPE>;
+
+//===----------------------------------------------------------------------===//
+// MIPS MT Instruction Definitions
+//===----------------------------------------------------------------------===//
+let hasSideEffects = 1, isNotDuplicable = 1,
+ AdditionalPredicates = [NotInMicroMips] in {
+ def DMT : DMT_ENC, DMT_DESC, ASE_MT;
+
+ def EMT : EMT_ENC, EMT_DESC, ASE_MT;
+
+ def DVPE : DVPE_ENC, DVPE_DESC, ASE_MT;
+
+ def EVPE : EVPE_ENC, EVPE_DESC, ASE_MT;
+
+ def FORK : FORK_ENC, FORK_DESC, ASE_MT;
+
+ def YIELD : YIELD_ENC, YIELD_DESC, ASE_MT;
+}
+
+//===----------------------------------------------------------------------===//
+// MIPS MT Instruction Definitions
+//===----------------------------------------------------------------------===//
+
+let AdditionalPredicates = [NotInMicroMips] in {
+ def : MipsInstAlias<"dmt", (DMT ZERO), 1>, ASE_MT;
+
+ def : MipsInstAlias<"emt", (EMT ZERO), 1>, ASE_MT;
+
+ def : MipsInstAlias<"dvpe", (DVPE ZERO), 1>, ASE_MT;
+
+ def : MipsInstAlias<"evpe", (EVPE ZERO), 1>, ASE_MT;
+
+ def : MipsInstAlias<"yield $rs", (YIELD ZERO, GPR32Opnd:$rs), 1>, ASE_MT;
+}
diff --git a/contrib/llvm/lib/Target/Mips/MipsMachineFunction.cpp b/contrib/llvm/lib/Target/Mips/MipsMachineFunction.cpp
index d0609b1..e01c03d 100644
--- a/contrib/llvm/lib/Target/Mips/MipsMachineFunction.cpp
+++ b/contrib/llvm/lib/Target/Mips/MipsMachineFunction.cpp
@@ -7,16 +7,15 @@
//
//===----------------------------------------------------------------------===//
-#include "MCTargetDesc/MipsBaseInfo.h"
-#include "MipsInstrInfo.h"
#include "MipsMachineFunction.h"
+#include "MCTargetDesc/MipsABIInfo.h"
#include "MipsSubtarget.h"
#include "MipsTargetMachine.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/IR/Function.h"
+#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetRegisterInfo.h"
using namespace llvm;
@@ -24,7 +23,7 @@ static cl::opt<bool>
FixGlobalBaseReg("mips-fix-global-base-reg", cl::Hidden, cl::init(true),
cl::desc("Always use $gp as the global base register."));
-MipsFunctionInfo::~MipsFunctionInfo() {}
+MipsFunctionInfo::~MipsFunctionInfo() = default;
bool MipsFunctionInfo::globalBaseRegSet() const {
return GlobalBaseReg;
@@ -54,14 +53,15 @@ unsigned MipsFunctionInfo::getGlobalBaseReg() {
}
void MipsFunctionInfo::createEhDataRegsFI() {
+ const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
for (int I = 0; I < 4; ++I) {
- const TargetRegisterClass *RC =
+ const TargetRegisterClass &RC =
static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI().IsN64()
- ? &Mips::GPR64RegClass
- : &Mips::GPR32RegClass;
+ ? Mips::GPR64RegClass
+ : Mips::GPR32RegClass;
- EhDataRegFI[I] = MF.getFrameInfo().CreateStackObject(RC->getSize(),
- RC->getAlignment(), false);
+ EhDataRegFI[I] = MF.getFrameInfo().CreateStackObject(TRI.getSpillSize(RC),
+ TRI.getSpillAlignment(RC), false);
}
}
@@ -70,11 +70,12 @@ void MipsFunctionInfo::createISRRegFI() {
// The current implementation only supports Mips32r2+ not Mips64rX. Status
// is always 32 bits, ErrorPC is 32 or 64 bits dependent on architecture,
// however Mips32r2+ is the supported architecture.
- const TargetRegisterClass *RC = &Mips::GPR32RegClass;
+ const TargetRegisterClass &RC = Mips::GPR32RegClass;
+ const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
for (int I = 0; I < 2; ++I)
ISRDataRegFI[I] = MF.getFrameInfo().CreateStackObject(
- RC->getSize(), RC->getAlignment(), false);
+ TRI.getSpillSize(RC), TRI.getSpillAlignment(RC), false);
}
bool MipsFunctionInfo::isEhDataRegFI(int FI) const {
@@ -94,11 +95,12 @@ MachinePointerInfo MipsFunctionInfo::callPtrInfo(const GlobalValue *GV) {
}
int MipsFunctionInfo::getMoveF64ViaSpillFI(const TargetRegisterClass *RC) {
+ const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
if (MoveF64ViaSpillFI == -1) {
MoveF64ViaSpillFI = MF.getFrameInfo().CreateStackObject(
- RC->getSize(), RC->getAlignment(), false);
+ TRI.getSpillSize(*RC), TRI.getSpillAlignment(*RC), false);
}
return MoveF64ViaSpillFI;
}
-void MipsFunctionInfo::anchor() { }
+void MipsFunctionInfo::anchor() {}
diff --git a/contrib/llvm/lib/Target/Mips/MipsMachineFunction.h b/contrib/llvm/lib/Target/Mips/MipsMachineFunction.h
index c9e5fdd..553a667 100644
--- a/contrib/llvm/lib/Target/Mips/MipsMachineFunction.h
+++ b/contrib/llvm/lib/Target/Mips/MipsMachineFunction.h
@@ -1,4 +1,4 @@
-//===-- MipsMachineFunctionInfo.h - Private data used for Mips ----*- C++ -*-=//
+//===- MipsMachineFunctionInfo.h - Private data used for Mips ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,12 +15,8 @@
#define LLVM_LIB_TARGET_MIPS_MIPSMACHINEFUNCTION_H
#include "Mips16HardFloatInfo.h"
-#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineMemOperand.h"
-#include "llvm/CodeGen/PseudoSourceValue.h"
-#include "llvm/Target/TargetFrameLowering.h"
-#include "llvm/Target/TargetMachine.h"
#include <map>
namespace llvm {
@@ -29,12 +25,9 @@ namespace llvm {
/// Mips target-specific information for each MachineFunction.
class MipsFunctionInfo : public MachineFunctionInfo {
public:
- MipsFunctionInfo(MachineFunction &MF)
- : MF(MF), SRetReturnReg(0), GlobalBaseReg(0), VarArgsFrameIndex(0),
- CallsEhReturn(false), IsISR(false), SaveS2(false),
- MoveF64ViaSpillFI(-1) {}
+ MipsFunctionInfo(MachineFunction &MF) : MF(MF) {}
- ~MipsFunctionInfo();
+ ~MipsFunctionInfo() override;
unsigned getSRetReturnReg() const { return SRetReturnReg; }
void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; }
@@ -81,25 +74,26 @@ public:
int getMoveF64ViaSpillFI(const TargetRegisterClass *RC);
- std::map<const char *, const llvm::Mips16HardFloatInfo::FuncSignature *>
+ std::map<const char *, const Mips16HardFloatInfo::FuncSignature *>
StubsNeeded;
private:
virtual void anchor();
MachineFunction& MF;
+
/// SRetReturnReg - Some subtargets require that sret lowering includes
/// returning the value of the returned struct in a register. This field
/// holds the virtual register into which the sret argument is passed.
- unsigned SRetReturnReg;
+ unsigned SRetReturnReg = 0;
/// GlobalBaseReg - keeps track of the virtual register initialized for
/// use as the global base register. This is used for PIC in some PIC
/// relocation models.
- unsigned GlobalBaseReg;
+ unsigned GlobalBaseReg = 0;
/// VarArgsFrameIndex - FrameIndex for start of varargs area.
- int VarArgsFrameIndex;
+ int VarArgsFrameIndex = 0;
/// True if function has a byval argument.
bool HasByvalArg;
@@ -108,25 +102,25 @@ private:
unsigned IncomingArgSize;
/// CallsEhReturn - Whether the function calls llvm.eh.return.
- bool CallsEhReturn;
+ bool CallsEhReturn = false;
/// Frame objects for spilling eh data registers.
int EhDataRegFI[4];
/// ISR - Whether the function is an Interrupt Service Routine.
- bool IsISR;
+ bool IsISR = false;
/// Frame objects for spilling C0_STATUS, C0_EPC
int ISRDataRegFI[2];
// saveS2
- bool SaveS2;
+ bool SaveS2 = false;
/// FrameIndex for expanding BuildPairF64 nodes to spill and reload when the
/// O32 FPXX ABI is enabled. -1 is used to denote invalid index.
- int MoveF64ViaSpillFI;
+ int MoveF64ViaSpillFI = -1;
};
-} // end of namespace llvm
+} // end namespace llvm
-#endif
+#endif // LLVM_LIB_TARGET_MIPS_MIPSMACHINEFUNCTION_H
diff --git a/contrib/llvm/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp b/contrib/llvm/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp
index cf85eb3..ceacaa4 100644
--- a/contrib/llvm/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp
+++ b/contrib/llvm/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp
@@ -10,6 +10,7 @@
#include "Mips.h"
#include "MipsTargetMachine.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
@@ -22,18 +23,19 @@ namespace {
public:
static char ID;
- explicit MipsModuleDAGToDAGISel(MipsTargetMachine &TM_)
- : MachineFunctionPass(ID), TM(TM_) {}
+ MipsModuleDAGToDAGISel() : MachineFunctionPass(ID) {}
// Pass Name
StringRef getPassName() const override {
return "MIPS DAG->DAG Pattern Instruction Selection";
}
- bool runOnMachineFunction(MachineFunction &MF) override;
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addRequired<TargetPassConfig>();
+ MachineFunctionPass::getAnalysisUsage(AU);
+ }
- protected:
- MipsTargetMachine &TM;
+ bool runOnMachineFunction(MachineFunction &MF) override;
};
char MipsModuleDAGToDAGISel::ID = 0;
@@ -41,10 +43,12 @@ namespace {
bool MipsModuleDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
DEBUG(errs() << "In MipsModuleDAGToDAGISel::runMachineFunction\n");
+ auto &TPC = getAnalysis<TargetPassConfig>();
+ auto &TM = TPC.getTM<MipsTargetMachine>();
TM.resetSubtarget(&MF);
return false;
}
-llvm::FunctionPass *llvm::createMipsModuleISelDagPass(MipsTargetMachine &TM) {
- return new MipsModuleDAGToDAGISel(TM);
+llvm::FunctionPass *llvm::createMipsModuleISelDagPass() {
+ return new MipsModuleDAGToDAGISel();
}
diff --git a/contrib/llvm/lib/Target/Mips/MipsOptimizePICCall.cpp b/contrib/llvm/lib/Target/Mips/MipsOptimizePICCall.cpp
index f33857f..79c8395 100644
--- a/contrib/llvm/lib/Target/Mips/MipsOptimizePICCall.cpp
+++ b/contrib/llvm/lib/Target/Mips/MipsOptimizePICCall.cpp
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#include "Mips.h"
#include "MCTargetDesc/MipsBaseInfo.h"
+#include "Mips.h"
#include "MipsMachineFunction.h"
#include "MipsTargetMachine.h"
#include "llvm/ADT/ScopedHashTable.h"
@@ -59,7 +59,7 @@ private:
class OptimizePICCall : public MachineFunctionPass {
public:
- OptimizePICCall(TargetMachine &tm) : MachineFunctionPass(ID) {}
+ OptimizePICCall() : MachineFunctionPass(ID) {}
StringRef getPassName() const override { return "Mips OptimizePICCall"; }
@@ -116,9 +116,10 @@ static MachineOperand *getCallTargetRegOpnd(MachineInstr &MI) {
/// Return type of register Reg.
static MVT::SimpleValueType getRegTy(unsigned Reg, MachineFunction &MF) {
+ const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
const TargetRegisterClass *RC = MF.getRegInfo().getRegClass(Reg);
- assert(RC->vt_end() - RC->vt_begin() == 1);
- return *RC->vt_begin();
+ assert(TRI.legalclasstypes_end(*RC) - TRI.legalclasstypes_begin(*RC) == 1);
+ return *TRI.legalclasstypes_begin(*RC);
}
/// Do the following transformation:
@@ -256,7 +257,7 @@ bool OptimizePICCall::isCallViaRegister(MachineInstr &MI, unsigned &Reg,
// Get the instruction that loads the function address from the GOT.
Reg = MO->getReg();
- Val = (Value*)nullptr;
+ Val = nullptr;
MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
MachineInstr *DefMI = MRI.getVRegDef(Reg);
@@ -296,6 +297,6 @@ void OptimizePICCall::incCntAndSetReg(ValueType Entry, unsigned Reg) {
}
/// Return an OptimizeCall object.
-FunctionPass *llvm::createMipsOptimizePICCallPass(MipsTargetMachine &TM) {
- return new OptimizePICCall(TM);
+FunctionPass *llvm::createMipsOptimizePICCallPass() {
+ return new OptimizePICCall();
}
diff --git a/contrib/llvm/lib/Target/Mips/MipsOptionRecord.h b/contrib/llvm/lib/Target/Mips/MipsOptionRecord.h
index 23f0b70..4708784 100644
--- a/contrib/llvm/lib/Target/Mips/MipsOptionRecord.h
+++ b/contrib/llvm/lib/Target/Mips/MipsOptionRecord.h
@@ -1,4 +1,4 @@
-//===-- MipsOptionRecord.h - Abstraction for storing information ----------===//
+//===- MipsOptionRecord.h - Abstraction for storing information -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -23,14 +23,16 @@
#include "MCTargetDesc/MipsMCTargetDesc.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCRegisterInfo.h"
+#include <cstdint>
namespace llvm {
+
class MipsELFStreamer;
-class MCSubtargetInfo;
class MipsOptionRecord {
public:
- virtual ~MipsOptionRecord(){};
+ virtual ~MipsOptionRecord() = default;
+
virtual void EmitMipsOptionRecord() = 0;
};
@@ -53,7 +55,8 @@ public:
COP2RegClass = &(TRI->getRegClass(Mips::COP2RegClassID));
COP3RegClass = &(TRI->getRegClass(Mips::COP3RegClassID));
}
- ~MipsRegInfoRecord() override {}
+
+ ~MipsRegInfoRecord() override = default;
void EmitMipsOptionRecord() override;
void SetPhysRegUsed(unsigned Reg, const MCRegisterInfo *MCRegInfo);
@@ -74,5 +77,7 @@ private:
uint32_t ri_cprmask[4];
int64_t ri_gp_value;
};
-} // namespace llvm
-#endif
+
+} // end namespace llvm
+
+#endif // LLVM_LIB_TARGET_MIPS_MIPSOPTIONRECORD_H
diff --git a/contrib/llvm/lib/Target/Mips/MipsOs16.cpp b/contrib/llvm/lib/Target/Mips/MipsOs16.cpp
index 51ac562..7ee45c2 100644
--- a/contrib/llvm/lib/Target/Mips/MipsOs16.cpp
+++ b/contrib/llvm/lib/Target/Mips/MipsOs16.cpp
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/IR/Instructions.h"
#include "Mips.h"
+#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
@@ -57,7 +57,7 @@ static bool needsFPFromSig(Function &F) {
;
}
if (F.arg_size() >=1) {
- Argument &Arg = F.getArgumentList().front();
+ Argument &Arg = *F.arg_begin();
switch (Arg.getType()->getTypeID()) {
case Type::FloatTyID:
case Type::DoubleTyID:
@@ -155,6 +155,4 @@ bool MipsOs16::runOnModule(Module &M) {
return modified;
}
-ModulePass *llvm::createMipsOs16Pass(MipsTargetMachine &TM) {
- return new MipsOs16;
-}
+ModulePass *llvm::createMipsOs16Pass() { return new MipsOs16(); }
diff --git a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.cpp b/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.cpp
index 65be350..de3389b 100644
--- a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.cpp
+++ b/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.cpp
@@ -286,7 +286,9 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
DEBUG(errs() << "FrameIndex : " << FrameIndex << "\n"
<< "spOffset : " << spOffset << "\n"
- << "stackSize : " << stackSize << "\n");
+ << "stackSize : " << stackSize << "\n"
+ << "alignment : "
+ << MF.getFrameInfo().getObjectAlignment(FrameIndex) << "\n");
eliminateFI(MI, FIOperandNum, FrameIndex, stackSize, spOffset);
}
diff --git a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.td b/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.td
index 8c82239..08fb3d7 100644
--- a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.td
+++ b/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.td
@@ -290,6 +290,25 @@ class GPR32Class<list<ValueType> regTypes> :
K0, K1, GP, SP, FP, RA)>;
def GPR32 : GPR32Class<[i32]>;
+
+def GPR32ZERO : RegisterClass<"Mips", [i32], 32, (add
+ // Reserved
+ ZERO)>;
+
+def GPR32NONZERO : RegisterClass<"Mips", [i32], 32, (add
+ // Reserved
+ AT,
+ // Return Values and Arguments
+ V0, V1, A0, A1, A2, A3,
+ // Not preserved across procedure calls
+ T0, T1, T2, T3, T4, T5, T6, T7,
+ // Callee save
+ S0, S1, S2, S3, S4, S5, S6, S7,
+ // Not preserved across procedure calls
+ T8, T9,
+ // Reserved
+ K0, K1, GP, SP, FP, RA)>;
+
def DSPR : GPR32Class<[v4i8, v2i16]>;
def GPRMM16 : RegisterClass<"Mips", [i32], 32, (add
@@ -317,7 +336,7 @@ def GPRMM16MoveP : RegisterClass<"Mips", [i32], 32, (add
S0, S2, S3, S4)>;
def GPR64 : RegisterClass<"Mips", [i64], 64, (add
-// Reserved
+ // Reserved
ZERO_64, AT_64,
// Return Values and Arguments
V0_64, V1_64, A0_64, A1_64, A2_64, A3_64,
@@ -479,6 +498,16 @@ def GPR64AsmOperand : MipsAsmRegOperand {
let PredicateMethod = "isGPRAsmReg";
}
+def GPR32ZeroAsmOperand : MipsAsmRegOperand {
+ let Name = "GPR32ZeroAsmReg";
+ let PredicateMethod = "isGPRZeroAsmReg";
+}
+
+def GPR32NonZeroAsmOperand : MipsAsmRegOperand {
+ let Name = "GPR32NonZeroAsmReg";
+ let PredicateMethod = "isGPRNonZeroAsmReg";
+}
+
def GPR32AsmOperand : MipsAsmRegOperand {
let Name = "GPR32AsmReg";
let PredicateMethod = "isGPRAsmReg";
@@ -523,16 +552,31 @@ def AFGR64AsmOperand : MipsAsmRegOperand {
let PredicateMethod = "isFGRAsmReg";
}
+def StrictlyAFGR64AsmOperand : MipsAsmRegOperand {
+ let Name = "StrictlyAFGR64AsmReg";
+ let PredicateMethod = "isStrictlyFGRAsmReg";
+}
+
def FGR64AsmOperand : MipsAsmRegOperand {
let Name = "FGR64AsmReg";
let PredicateMethod = "isFGRAsmReg";
}
+def StrictlyFGR64AsmOperand : MipsAsmRegOperand {
+ let Name = "StrictlyFGR64AsmReg";
+ let PredicateMethod = "isStrictlyFGRAsmReg";
+}
+
def FGR32AsmOperand : MipsAsmRegOperand {
let Name = "FGR32AsmReg";
let PredicateMethod = "isFGRAsmReg";
}
+def StrictlyFGR32AsmOperand : MipsAsmRegOperand {
+ let Name = "StrictlyFGR32AsmReg";
+ let PredicateMethod = "isStrictlyFGRAsmReg";
+}
+
def FGRH32AsmOperand : MipsAsmRegOperand {
let Name = "FGRH32AsmReg";
let PredicateMethod = "isFGRAsmReg";
@@ -550,6 +594,14 @@ def MSACtrlAsmOperand : MipsAsmRegOperand {
let Name = "MSACtrlAsmReg";
}
+def GPR32ZeroOpnd : RegisterOperand<GPR32ZERO> {
+ let ParserMatchClass = GPR32ZeroAsmOperand;
+}
+
+def GPR32NonZeroOpnd : RegisterOperand<GPR32NONZERO> {
+ let ParserMatchClass = GPR32NonZeroAsmOperand;
+}
+
def GPR32Opnd : RegisterOperand<GPR32> {
let ParserMatchClass = GPR32AsmOperand;
}
@@ -602,14 +654,26 @@ def AFGR64Opnd : RegisterOperand<AFGR64> {
let ParserMatchClass = AFGR64AsmOperand;
}
+def StrictlyAFGR64Opnd : RegisterOperand<AFGR64> {
+ let ParserMatchClass = StrictlyAFGR64AsmOperand;
+}
+
def FGR64Opnd : RegisterOperand<FGR64> {
let ParserMatchClass = FGR64AsmOperand;
}
+def StrictlyFGR64Opnd : RegisterOperand<FGR64> {
+ let ParserMatchClass = StrictlyFGR64AsmOperand;
+}
+
def FGR32Opnd : RegisterOperand<FGR32> {
let ParserMatchClass = FGR32AsmOperand;
}
+def StrictlyFGR32Opnd : RegisterOperand<FGR32> {
+ let ParserMatchClass = StrictlyFGR32AsmOperand;
+}
+
def FGRCCOpnd : RegisterOperand<FGRCC> {
// The assembler doesn't use register classes so we can re-use
// FGR32AsmOperand.
diff --git a/contrib/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp b/contrib/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp
index 4996d07..102ebb2 100644
--- a/contrib/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp
+++ b/contrib/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp
@@ -12,26 +12,41 @@
//===----------------------------------------------------------------------===//
#include "MipsSEFrameLowering.h"
-#include "MCTargetDesc/MipsBaseInfo.h"
+#include "MCTargetDesc/MipsABIInfo.h"
#include "MipsMachineFunction.h"
+#include "MipsRegisterInfo.h"
#include "MipsSEInstrInfo.h"
#include "MipsSubtarget.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
-#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Function.h"
-#include "llvm/Target/TargetOptions.h"
+#include "llvm/MC/MCDwarf.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MachineLocation.h"
+#include "llvm/Support/CodeGen.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
+#include <cassert>
+#include <cstdint>
+#include <utility>
+#include <vector>
using namespace llvm;
-namespace {
-typedef MachineBasicBlock::iterator Iter;
-
static std::pair<unsigned, unsigned> getMFHiLoOpc(unsigned Src) {
if (Mips::ACC64RegClass.contains(Src))
return std::make_pair((unsigned)Mips::PseudoMFHI,
@@ -47,6 +62,8 @@ static std::pair<unsigned, unsigned> getMFHiLoOpc(unsigned Src) {
return std::make_pair(0, 0);
}
+namespace {
+
/// Helper class to expand pseudos.
class ExpandPseudo {
public:
@@ -54,6 +71,8 @@ public:
bool expand();
private:
+ typedef MachineBasicBlock::iterator Iter;
+
bool expandInstr(MachineBasicBlock &MBB, Iter I);
void expandLoadCCond(MachineBasicBlock &MBB, Iter I);
void expandStoreCCond(MachineBasicBlock &MBB, Iter I);
@@ -74,7 +93,8 @@ private:
const MipsSEInstrInfo &TII;
const MipsRegisterInfo &RegInfo;
};
-}
+
+} // end anonymous namespace
ExpandPseudo::ExpandPseudo(MachineFunction &MF_)
: MF(MF_), MRI(MF.getRegInfo()),
@@ -240,7 +260,8 @@ bool ExpandPseudo::expandCopyACC(MachineBasicBlock &MBB, Iter I,
// copy dst_hi, $vr1
unsigned Dst = I->getOperand(0).getReg(), Src = I->getOperand(1).getReg();
- unsigned VRegSize = RegInfo.getMinimalPhysRegClass(Dst)->getSize() / 2;
+ const TargetRegisterClass *DstRC = RegInfo.getMinimalPhysRegClass(Dst);
+ unsigned VRegSize = RegInfo.getRegSizeInBits(*DstRC) / 16;
const TargetRegisterClass *RC = RegInfo.intRegClass(VRegSize);
unsigned VR0 = MRI.createVirtualRegister(RC);
unsigned VR1 = MRI.createVirtualRegister(RC);
@@ -419,7 +440,7 @@ void MipsSEFrameLowering::emitPrologue(MachineFunction &MF,
const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
- if (CSI.size()) {
+ if (!CSI.empty()) {
// Find the instruction past the last instruction that saves a callee-saved
// register to the stack.
for (unsigned i = 0; i < CSI.size(); ++i)
@@ -471,7 +492,7 @@ void MipsSEFrameLowering::emitPrologue(MachineFunction &MF,
} else {
// Reg is either in GPR32 or FGR32.
unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
- nullptr, MRI->getDwarfRegNum(Reg, 1), Offset));
+ nullptr, MRI->getDwarfRegNum(Reg, true), Offset));
BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex);
}
@@ -534,7 +555,6 @@ void MipsSEFrameLowering::emitPrologue(MachineFunction &MF,
void MipsSEFrameLowering::emitInterruptPrologueStub(
MachineFunction &MF, MachineBasicBlock &MBB) const {
-
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
MachineBasicBlock::iterator MBBI = MBB.begin();
DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
@@ -722,7 +742,6 @@ void MipsSEFrameLowering::emitEpilogue(MachineFunction &MF,
void MipsSEFrameLowering::emitInterruptEpilogueStub(
MachineFunction &MF, MachineBasicBlock &MBB) const {
-
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
@@ -820,7 +839,6 @@ spillCalleeSavedRegisters(MachineBasicBlock &MBB,
bool
MipsSEFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
const MachineFrameInfo &MFI = MF.getFrameInfo();
-
// Reserve call frame if the size of the maximum call frame fits into 16-bit
// immediate field and there are no variable sized objects on the stack.
// Make sure the second register scavenger spill slot can be accessed with one
@@ -841,6 +859,7 @@ void MipsSEFrameLowering::determineCalleeSaves(MachineFunction &MF,
BitVector &SavedRegs,
RegScavenger *RS) const {
TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
+ const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
MipsABIInfo ABI = STI.getABI();
unsigned FP = ABI.GetFramePtr();
@@ -866,10 +885,11 @@ void MipsSEFrameLowering::determineCalleeSaves(MachineFunction &MF,
if (ExpandPseudo(MF).expand()) {
// The spill slot should be half the size of the accumulator. If target is
// mips64, it should be 64-bit, otherwise it should be 32-bt.
- const TargetRegisterClass *RC = STI.hasMips64() ?
- &Mips::GPR64RegClass : &Mips::GPR32RegClass;
- int FI = MF.getFrameInfo().CreateStackObject(RC->getSize(),
- RC->getAlignment(), false);
+ const TargetRegisterClass &RC = STI.hasMips64() ?
+ Mips::GPR64RegClass : Mips::GPR32RegClass;
+ int FI = MF.getFrameInfo().CreateStackObject(TRI->getSpillSize(RC),
+ TRI->getSpillAlignment(RC),
+ false);
RS->addScavengingFrameIndex(FI);
}
@@ -880,10 +900,11 @@ void MipsSEFrameLowering::determineCalleeSaves(MachineFunction &MF,
if (isInt<16>(MaxSPOffset))
return;
- const TargetRegisterClass *RC =
- ABI.ArePtrs64bit() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
- int FI = MF.getFrameInfo().CreateStackObject(RC->getSize(),
- RC->getAlignment(), false);
+ const TargetRegisterClass &RC =
+ ABI.ArePtrs64bit() ? Mips::GPR64RegClass : Mips::GPR32RegClass;
+ int FI = MF.getFrameInfo().CreateStackObject(TRI->getSpillSize(RC),
+ TRI->getSpillAlignment(RC),
+ false);
RS->addScavengingFrameIndex(FI);
}
diff --git a/contrib/llvm/lib/Target/Mips/MipsSEFrameLowering.h b/contrib/llvm/lib/Target/Mips/MipsSEFrameLowering.h
index 63cd3ce..bf30deb 100644
--- a/contrib/llvm/lib/Target/Mips/MipsSEFrameLowering.h
+++ b/contrib/llvm/lib/Target/Mips/MipsSEFrameLowering.h
@@ -1,4 +1,4 @@
-//===-- MipsSEFrameLowering.h - Mips32/64 frame lowering --------*- C++ -*-===//
+//===- MipsSEFrameLowering.h - Mips32/64 frame lowering ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,6 +15,8 @@
#define LLVM_LIB_TARGET_MIPS_MIPSSEFRAMELOWERING_H
#include "MipsFrameLowering.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include <vector>
namespace llvm {
@@ -47,6 +49,7 @@ private:
void emitInterruptPrologueStub(MachineFunction &MF,
MachineBasicBlock &MBB) const;
};
-} // End llvm namespace
-#endif
+} // end namespace llvm
+
+#endif // LLVM_LIB_TARGET_MIPS_MIPSSEFRAMELOWERING_H
diff --git a/contrib/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp b/contrib/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
index 92d3c00..4be26dd 100644
--- a/contrib/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
+++ b/contrib/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
@@ -24,11 +24,11 @@
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/IR/CFG.h"
+#include "llvm/IR/Dominators.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Type.h"
-#include "llvm/IR/Dominators.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
@@ -97,11 +97,13 @@ bool MipsSEDAGToDAGISel::replaceUsesWithZeroReg(MachineRegisterInfo *MRI,
// Check if MI is "addiu $dst, $zero, 0" or "daddiu $dst, $zero, 0".
if ((MI.getOpcode() == Mips::ADDiu) &&
(MI.getOperand(1).getReg() == Mips::ZERO) &&
+ (MI.getOperand(2).isImm()) &&
(MI.getOperand(2).getImm() == 0)) {
DstReg = MI.getOperand(0).getReg();
ZeroReg = Mips::ZERO;
} else if ((MI.getOpcode() == Mips::DADDiu) &&
(MI.getOperand(1).getReg() == Mips::ZERO_64) &&
+ (MI.getOperand(2).isImm()) &&
(MI.getOperand(2).getImm() == 0)) {
DstReg = MI.getOperand(0).getReg();
ZeroReg = Mips::ZERO_64;
@@ -243,46 +245,64 @@ void MipsSEDAGToDAGISel::processFunctionAfterISel(MachineFunction &MF) {
}
}
-void MipsSEDAGToDAGISel::selectAddESubE(unsigned MOp, SDValue InFlag,
- SDValue CmpLHS, const SDLoc &DL,
- SDNode *Node) const {
- unsigned Opc = InFlag.getOpcode(); (void)Opc;
-
- assert(((Opc == ISD::ADDC || Opc == ISD::ADDE) ||
- (Opc == ISD::SUBC || Opc == ISD::SUBE)) &&
- "(ADD|SUB)E flag operand must come from (ADD|SUB)C/E insn");
-
- unsigned SLTuOp = Mips::SLTu, ADDuOp = Mips::ADDu;
- if (Subtarget->isGP64bit()) {
- SLTuOp = Mips::SLTu64;
- ADDuOp = Mips::DADDu;
- }
-
- SDValue Ops[] = { CmpLHS, InFlag.getOperand(1) };
+void MipsSEDAGToDAGISel::selectAddE(SDNode *Node, const SDLoc &DL) const {
+ SDValue InFlag = Node->getOperand(2);
+ unsigned Opc = InFlag.getOpcode();
SDValue LHS = Node->getOperand(0), RHS = Node->getOperand(1);
EVT VT = LHS.getValueType();
- SDNode *Carry = CurDAG->getMachineNode(SLTuOp, DL, VT, Ops);
-
- if (Subtarget->isGP64bit()) {
- // On 64-bit targets, sltu produces an i64 but our backend currently says
- // that SLTu64 produces an i32. We need to fix this in the long run but for
- // now, just make the DAG type-correct by asserting the upper bits are zero.
- Carry = CurDAG->getMachineNode(Mips::SUBREG_TO_REG, DL, VT,
- CurDAG->getTargetConstant(0, DL, VT),
- SDValue(Carry, 0),
- CurDAG->getTargetConstant(Mips::sub_32, DL,
- VT));
+ // In the base case, we can rely on the carry bit from the addsc
+ // instruction.
+ if (Opc == ISD::ADDC) {
+ SDValue Ops[3] = {LHS, RHS, InFlag};
+ CurDAG->SelectNodeTo(Node, Mips::ADDWC, VT, MVT::Glue, Ops);
+ return;
}
- // Generate a second addition only if we know that RHS is not a
- // constant-zero node.
- SDNode *AddCarry = Carry;
- ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS);
- if (!C || C->getZExtValue())
- AddCarry = CurDAG->getMachineNode(ADDuOp, DL, VT, SDValue(Carry, 0), RHS);
+ assert(Opc == ISD::ADDE && "ISD::ADDE not in a chain of ADDE nodes!");
+
+ // The more complex case is when there is a chain of ISD::ADDE nodes like:
+ // (adde (adde (adde (addc a b) c) d) e).
+ //
+ // The addwc instruction does not write to the carry bit, instead it writes
+ // to bit 20 of the dsp control register. To match this series of nodes, each
+ // intermediate adde node must be expanded to write the carry bit before the
+ // addition.
+
+ // Start by reading the overflow field for addsc and moving the value to the
+ // carry field. The usage of 1 here with MipsISD::RDDSP / Mips::WRDSP
+ // corresponds to reading/writing the entire control register to/from a GPR.
+
+ SDValue CstOne = CurDAG->getTargetConstant(1, DL, MVT::i32);
+
+ SDValue OuFlag = CurDAG->getTargetConstant(20, DL, MVT::i32);
+
+ SDNode *DSPCtrlField =
+ CurDAG->getMachineNode(Mips::RDDSP, DL, MVT::i32, MVT::Glue, CstOne, InFlag);
+
+ SDNode *Carry = CurDAG->getMachineNode(
+ Mips::EXT, DL, MVT::i32, SDValue(DSPCtrlField, 0), OuFlag, CstOne);
- CurDAG->SelectNodeTo(Node, MOp, VT, MVT::Glue, LHS, SDValue(AddCarry, 0));
+ SDValue Ops[4] = {SDValue(DSPCtrlField, 0),
+ CurDAG->getTargetConstant(6, DL, MVT::i32), CstOne,
+ SDValue(Carry, 0)};
+ SDNode *DSPCFWithCarry = CurDAG->getMachineNode(Mips::INS, DL, MVT::i32, Ops);
+
+ // My reading of the the MIPS DSP 3.01 specification isn't as clear as I
+ // would like about whether bit 20 always gets overwritten by addwc.
+ // Hence take an extremely conservative view and presume it's sticky. We
+ // therefore need to clear it.
+
+ SDValue Zero = CurDAG->getRegister(Mips::ZERO, MVT::i32);
+
+ SDValue InsOps[4] = {Zero, OuFlag, CstOne, SDValue(DSPCFWithCarry, 0)};
+ SDNode *DSPCtrlFinal = CurDAG->getMachineNode(Mips::INS, DL, MVT::i32, InsOps);
+
+ SDNode *WrDSP = CurDAG->getMachineNode(Mips::WRDSP, DL, MVT::Glue,
+ SDValue(DSPCtrlFinal, 0), CstOne);
+
+ SDValue Operands[3] = {LHS, RHS, SDValue(WrDSP, 0)};
+ CurDAG->SelectNodeTo(Node, Mips::ADDWC, VT, MVT::Glue, Operands);
}
/// Match frameindex
@@ -690,7 +710,7 @@ bool MipsSEDAGToDAGISel::selectVSplatMaskL(SDValue N, SDValue &Imm) const {
// as the original value.
if (ImmValue == ~(~ImmValue & ~(~ImmValue + 1))) {
- Imm = CurDAG->getTargetConstant(ImmValue.countPopulation(), SDLoc(N),
+ Imm = CurDAG->getTargetConstant(ImmValue.countPopulation() - 1, SDLoc(N),
EltTy);
return true;
}
@@ -722,7 +742,7 @@ bool MipsSEDAGToDAGISel::selectVSplatMaskR(SDValue N, SDValue &Imm) const {
// Extract the run of set bits starting with bit zero, and test that the
// result is the same as the original value
if (ImmValue == (ImmValue & ~(ImmValue + 1))) {
- Imm = CurDAG->getTargetConstant(ImmValue.countPopulation(), SDLoc(N),
+ Imm = CurDAG->getTargetConstant(ImmValue.countPopulation() - 1, SDLoc(N),
EltTy);
return true;
}
@@ -763,19 +783,8 @@ bool MipsSEDAGToDAGISel::trySelect(SDNode *Node) {
switch(Opcode) {
default: break;
- case ISD::SUBE: {
- SDValue InFlag = Node->getOperand(2);
- unsigned Opc = Subtarget->isGP64bit() ? Mips::DSUBu : Mips::SUBu;
- selectAddESubE(Opc, InFlag, InFlag.getOperand(0), DL, Node);
- return true;
- }
-
case ISD::ADDE: {
- if (Subtarget->hasDSP()) // Select DSP instructions, ADDSC and ADDWC.
- break;
- SDValue InFlag = Node->getOperand(2);
- unsigned Opc = Subtarget->isGP64bit() ? Mips::DADDu : Mips::ADDu;
- selectAddESubE(Opc, InFlag, InFlag.getValue(0), DL, Node);
+ selectAddE(Node, DL);
return true;
}
@@ -932,6 +941,9 @@ bool MipsSEDAGToDAGISel::trySelect(SDNode *Node) {
// same set/ of registers. Similarly, ldi.h isn't capable of producing {
// 0x00000000, 0x00000001, 0x00000000, 0x00000001 } but 'ldi.d wd, 1' can.
+ const MipsABIInfo &ABI =
+ static_cast<const MipsTargetMachine &>(TM).getABI();
+
BuildVectorSDNode *BVN = cast<BuildVectorSDNode>(Node);
APInt SplatValue, SplatUndef;
unsigned SplatBitSize;
@@ -969,13 +981,233 @@ bool MipsSEDAGToDAGISel::trySelect(SDNode *Node) {
break;
}
- if (!SplatValue.isSignedIntN(10))
- return false;
+ SDNode *Res;
- SDValue Imm = CurDAG->getTargetConstant(SplatValue, DL,
- ViaVecTy.getVectorElementType());
-
- SDNode *Res = CurDAG->getMachineNode(LdiOp, DL, ViaVecTy, Imm);
+ // If we have a signed 10 bit integer, we can splat it directly.
+ //
+ // If we have something bigger we can synthesize the value into a GPR and
+ // splat from there.
+ if (SplatValue.isSignedIntN(10)) {
+ SDValue Imm = CurDAG->getTargetConstant(SplatValue, DL,
+ ViaVecTy.getVectorElementType());
+
+ Res = CurDAG->getMachineNode(LdiOp, DL, ViaVecTy, Imm);
+ } else if (SplatValue.isSignedIntN(16) &&
+ ((ABI.IsO32() && SplatBitSize < 64) ||
+ (ABI.IsN32() || ABI.IsN64()))) {
+ // Only handle signed 16 bit values when the element size is GPR width.
+ // MIPS64 can handle all the cases but MIPS32 would need to handle
+ // negative cases specifically here. Instead, handle those cases as
+ // 64bit values.
+
+ bool Is32BitSplat = ABI.IsO32() || SplatBitSize < 64;
+ const unsigned ADDiuOp = Is32BitSplat ? Mips::ADDiu : Mips::DADDiu;
+ const MVT SplatMVT = Is32BitSplat ? MVT::i32 : MVT::i64;
+ SDValue ZeroVal = CurDAG->getRegister(
+ Is32BitSplat ? Mips::ZERO : Mips::ZERO_64, SplatMVT);
+
+ const unsigned FILLOp =
+ SplatBitSize == 16
+ ? Mips::FILL_H
+ : (SplatBitSize == 32 ? Mips::FILL_W
+ : (SplatBitSize == 64 ? Mips::FILL_D : 0));
+
+ assert(FILLOp != 0 && "Unknown FILL Op for splat synthesis!");
+ assert((!ABI.IsO32() || (FILLOp != Mips::FILL_D)) &&
+ "Attempting to use fill.d on MIPS32!");
+
+ const unsigned Lo = SplatValue.getLoBits(16).getZExtValue();
+ SDValue LoVal = CurDAG->getTargetConstant(Lo, DL, SplatMVT);
+
+ Res = CurDAG->getMachineNode(ADDiuOp, DL, SplatMVT, ZeroVal, LoVal);
+ Res = CurDAG->getMachineNode(FILLOp, DL, ViaVecTy, SDValue(Res, 0));
+
+ } else if (SplatValue.isSignedIntN(32) && SplatBitSize == 32) {
+ // Only handle the cases where the splat size agrees with the size
+ // of the SplatValue here.
+ const unsigned Lo = SplatValue.getLoBits(16).getZExtValue();
+ const unsigned Hi = SplatValue.lshr(16).getLoBits(16).getZExtValue();
+ SDValue ZeroVal = CurDAG->getRegister(Mips::ZERO, MVT::i32);
+
+ SDValue LoVal = CurDAG->getTargetConstant(Lo, DL, MVT::i32);
+ SDValue HiVal = CurDAG->getTargetConstant(Hi, DL, MVT::i32);
+
+ if (Hi)
+ Res = CurDAG->getMachineNode(Mips::LUi, DL, MVT::i32, HiVal);
+
+ if (Lo)
+ Res = CurDAG->getMachineNode(Mips::ORi, DL, MVT::i32,
+ Hi ? SDValue(Res, 0) : ZeroVal, LoVal);
+
+ assert((Hi || Lo) && "Zero case reached 32 bit case splat synthesis!");
+ Res = CurDAG->getMachineNode(Mips::FILL_W, DL, MVT::v4i32, SDValue(Res, 0));
+
+ } else if (SplatValue.isSignedIntN(32) && SplatBitSize == 64 &&
+ (ABI.IsN32() || ABI.IsN64())) {
+ // N32 and N64 can perform some tricks that O32 can't for signed 32 bit
+ // integers due to having 64bit registers. lui will cause the necessary
+ // zero/sign extension.
+ const unsigned Lo = SplatValue.getLoBits(16).getZExtValue();
+ const unsigned Hi = SplatValue.lshr(16).getLoBits(16).getZExtValue();
+ SDValue ZeroVal = CurDAG->getRegister(Mips::ZERO, MVT::i32);
+
+ SDValue LoVal = CurDAG->getTargetConstant(Lo, DL, MVT::i32);
+ SDValue HiVal = CurDAG->getTargetConstant(Hi, DL, MVT::i32);
+
+ if (Hi)
+ Res = CurDAG->getMachineNode(Mips::LUi, DL, MVT::i32, HiVal);
+
+ if (Lo)
+ Res = CurDAG->getMachineNode(Mips::ORi, DL, MVT::i32,
+ Hi ? SDValue(Res, 0) : ZeroVal, LoVal);
+
+ Res = CurDAG->getMachineNode(
+ Mips::SUBREG_TO_REG, DL, MVT::i64,
+ CurDAG->getTargetConstant(((Hi >> 15) & 0x1), DL, MVT::i64),
+ SDValue(Res, 0),
+ CurDAG->getTargetConstant(Mips::sub_32, DL, MVT::i64));
+
+ Res =
+ CurDAG->getMachineNode(Mips::FILL_D, DL, MVT::v2i64, SDValue(Res, 0));
+
+ } else if (SplatValue.isSignedIntN(64)) {
+ // If we have a 64 bit Splat value, we perform a similar sequence to the
+ // above:
+ //
+ // MIPS32: MIPS64:
+ // lui $res, %highest(val) lui $res, %highest(val)
+ // ori $res, $res, %higher(val) ori $res, $res, %higher(val)
+ // lui $res2, %hi(val) lui $res2, %hi(val)
+ // ori $res2, %res2, %lo(val) ori $res2, %res2, %lo(val)
+ // $res3 = fill $res2 dinsu $res, $res2, 0, 32
+ // $res4 = insert.w $res3[1], $res fill.d $res
+ // splat.d $res4, 0
+ //
+ // The ability to use dinsu is guaranteed as MSA requires MIPSR5. This saves
+ // having to materialize the value by shifts and ors.
+ //
+ // FIXME: Implement the preferred sequence for MIPS64R6:
+ //
+ // MIPS64R6:
+ // ori $res, $zero, %lo(val)
+ // daui $res, $res, %hi(val)
+ // dahi $res, $res, %higher(val)
+ // dati $res, $res, %highest(cal)
+ // fill.d $res
+ //
+
+ const unsigned Lo = SplatValue.getLoBits(16).getZExtValue();
+ const unsigned Hi = SplatValue.lshr(16).getLoBits(16).getZExtValue();
+ const unsigned Higher = SplatValue.lshr(32).getLoBits(16).getZExtValue();
+ const unsigned Highest = SplatValue.lshr(48).getLoBits(16).getZExtValue();
+
+ SDValue LoVal = CurDAG->getTargetConstant(Lo, DL, MVT::i32);
+ SDValue HiVal = CurDAG->getTargetConstant(Hi, DL, MVT::i32);
+ SDValue HigherVal = CurDAG->getTargetConstant(Higher, DL, MVT::i32);
+ SDValue HighestVal = CurDAG->getTargetConstant(Highest, DL, MVT::i32);
+ SDValue ZeroVal = CurDAG->getRegister(Mips::ZERO, MVT::i32);
+
+ // Independent of whether we're targeting MIPS64 or not, the basic
+ // operations are the same. Also, directly use the $zero register if
+ // the 16 bit chunk is zero.
+ //
+ // For optimization purposes we always synthesize the splat value as
+ // an i32 value, then if we're targetting MIPS64, use SUBREG_TO_REG
+ // just before combining the values with dinsu to produce an i64. This
+ // enables SelectionDAG to aggressively share components of splat values
+ // where possible.
+ //
+ // FIXME: This is the general constant synthesis problem. This code
+ // should be factored out into a class shared between all the
+ // classes that need it. Specifically, for a splat size of 64
+ // bits that's a negative number we can do better than LUi/ORi
+ // for the upper 32bits.
+
+ if (Hi)
+ Res = CurDAG->getMachineNode(Mips::LUi, DL, MVT::i32, HiVal);
+
+ if (Lo)
+ Res = CurDAG->getMachineNode(Mips::ORi, DL, MVT::i32,
+ Hi ? SDValue(Res, 0) : ZeroVal, LoVal);
+
+ SDNode *HiRes;
+ if (Highest)
+ HiRes = CurDAG->getMachineNode(Mips::LUi, DL, MVT::i32, HighestVal);
+
+ if (Higher)
+ HiRes = CurDAG->getMachineNode(Mips::ORi, DL, MVT::i32,
+ Highest ? SDValue(HiRes, 0) : ZeroVal,
+ HigherVal);
+
+
+ if (ABI.IsO32()) {
+ Res = CurDAG->getMachineNode(Mips::FILL_W, DL, MVT::v4i32,
+ (Hi || Lo) ? SDValue(Res, 0) : ZeroVal);
+
+ Res = CurDAG->getMachineNode(
+ Mips::INSERT_W, DL, MVT::v4i32, SDValue(Res, 0),
+ (Highest || Higher) ? SDValue(HiRes, 0) : ZeroVal,
+ CurDAG->getTargetConstant(1, DL, MVT::i32));
+
+ const TargetLowering *TLI = getTargetLowering();
+ const TargetRegisterClass *RC =
+ TLI->getRegClassFor(ViaVecTy.getSimpleVT());
+
+ Res = CurDAG->getMachineNode(
+ Mips::COPY_TO_REGCLASS, DL, ViaVecTy, SDValue(Res, 0),
+ CurDAG->getTargetConstant(RC->getID(), DL, MVT::i32));
+
+ Res = CurDAG->getMachineNode(
+ Mips::SPLATI_D, DL, MVT::v2i64, SDValue(Res, 0),
+ CurDAG->getTargetConstant(0, DL, MVT::i32));
+ } else if (ABI.IsN64() || ABI.IsN32()) {
+
+ SDValue Zero64Val = CurDAG->getRegister(Mips::ZERO_64, MVT::i64);
+ const bool HiResNonZero = Highest || Higher;
+ const bool ResNonZero = Hi || Lo;
+
+ if (HiResNonZero)
+ HiRes = CurDAG->getMachineNode(
+ Mips::SUBREG_TO_REG, DL, MVT::i64,
+ CurDAG->getTargetConstant(((Highest >> 15) & 0x1), DL, MVT::i64),
+ SDValue(HiRes, 0),
+ CurDAG->getTargetConstant(Mips::sub_32, DL, MVT::i64));
+
+ if (ResNonZero)
+ Res = CurDAG->getMachineNode(
+ Mips::SUBREG_TO_REG, DL, MVT::i64,
+ CurDAG->getTargetConstant(((Hi >> 15) & 0x1), DL, MVT::i64),
+ SDValue(Res, 0),
+ CurDAG->getTargetConstant(Mips::sub_32, DL, MVT::i64));
+
+ // We have 3 cases:
+ // The HiRes is nonzero but Res is $zero => dsll32 HiRes, 0
+ // The Res is nonzero but HiRes is $zero => dinsu Res, $zero, 32, 32
+ // Both are non zero => dinsu Res, HiRes, 32, 32
+ //
+ // The obvious "missing" case is when both are zero, but that case is
+ // handled by the ldi case.
+ if (ResNonZero) {
+ SDValue Ops[4] = {HiResNonZero ? SDValue(HiRes, 0) : Zero64Val,
+ CurDAG->getTargetConstant(64, DL, MVT::i32),
+ CurDAG->getTargetConstant(32, DL, MVT::i32),
+ SDValue(Res, 0)};
+
+ Res = CurDAG->getMachineNode(Mips::DINSU, DL, MVT::i64, Ops);
+ } else if (HiResNonZero) {
+ Res = CurDAG->getMachineNode(
+ Mips::DSLL32, DL, MVT::i64, SDValue(HiRes, 0),
+ CurDAG->getTargetConstant(0, DL, MVT::i32));
+ } else
+ llvm_unreachable(
+ "Zero splat value handled by non-zero 64bit splat synthesis!");
+
+ Res = CurDAG->getMachineNode(Mips::FILL_D, DL, MVT::v2i64, SDValue(Res, 0));
+ } else
+ llvm_unreachable("Unknown ABI in MipsISelDAGToDAG!");
+
+ } else
+ return false;
if (ResVecTy != ViaVecTy) {
// If LdiOp is writing to a different register class to ResVecTy, then
diff --git a/contrib/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.h b/contrib/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.h
index f89a350..6f38289 100644
--- a/contrib/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.h
+++ b/contrib/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.h
@@ -41,8 +41,7 @@ private:
const SDLoc &dl, EVT Ty, bool HasLo,
bool HasHi);
- void selectAddESubE(unsigned MOp, SDValue InFlag, SDValue CmpLHS,
- const SDLoc &DL, SDNode *Node) const;
+ void selectAddE(SDNode *Node, const SDLoc &DL) const;
bool selectAddrFrameIndex(SDValue Addr, SDValue &Base, SDValue &Offset) const;
bool selectAddrFrameIndexOffset(SDValue Addr, SDValue &Base, SDValue &Offset,
diff --git a/contrib/llvm/lib/Target/Mips/MipsSEISelLowering.cpp b/contrib/llvm/lib/Target/Mips/MipsSEISelLowering.cpp
index f28e8b3..72b2738 100644
--- a/contrib/llvm/lib/Target/Mips/MipsSEISelLowering.cpp
+++ b/contrib/llvm/lib/Target/Mips/MipsSEISelLowering.cpp
@@ -179,8 +179,6 @@ MipsSETargetLowering::MipsSETargetLowering(const MipsTargetMachine &TM,
setOperationAction(ISD::LOAD, MVT::i32, Custom);
setOperationAction(ISD::STORE, MVT::i32, Custom);
- setTargetDAGCombine(ISD::ADDE);
- setTargetDAGCombine(ISD::SUBE);
setTargetDAGCombine(ISD::MUL);
setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
@@ -421,163 +419,6 @@ SDValue MipsSETargetLowering::LowerOperation(SDValue Op,
return MipsTargetLowering::LowerOperation(Op, DAG);
}
-// selectMADD -
-// Transforms a subgraph in CurDAG if the following pattern is found:
-// (addc multLo, Lo0), (adde multHi, Hi0),
-// where,
-// multHi/Lo: product of multiplication
-// Lo0: initial value of Lo register
-// Hi0: initial value of Hi register
-// Return true if pattern matching was successful.
-static bool selectMADD(SDNode *ADDENode, SelectionDAG *CurDAG) {
- // ADDENode's second operand must be a flag output of an ADDC node in order
- // for the matching to be successful.
- SDNode *ADDCNode = ADDENode->getOperand(2).getNode();
-
- if (ADDCNode->getOpcode() != ISD::ADDC)
- return false;
-
- SDValue MultHi = ADDENode->getOperand(0);
- SDValue MultLo = ADDCNode->getOperand(0);
- SDNode *MultNode = MultHi.getNode();
- unsigned MultOpc = MultHi.getOpcode();
-
- // MultHi and MultLo must be generated by the same node,
- if (MultLo.getNode() != MultNode)
- return false;
-
- // and it must be a multiplication.
- if (MultOpc != ISD::SMUL_LOHI && MultOpc != ISD::UMUL_LOHI)
- return false;
-
- // MultLo amd MultHi must be the first and second output of MultNode
- // respectively.
- if (MultHi.getResNo() != 1 || MultLo.getResNo() != 0)
- return false;
-
- // Transform this to a MADD only if ADDENode and ADDCNode are the only users
- // of the values of MultNode, in which case MultNode will be removed in later
- // phases.
- // If there exist users other than ADDENode or ADDCNode, this function returns
- // here, which will result in MultNode being mapped to a single MULT
- // instruction node rather than a pair of MULT and MADD instructions being
- // produced.
- if (!MultHi.hasOneUse() || !MultLo.hasOneUse())
- return false;
-
- SDLoc DL(ADDENode);
-
- // Initialize accumulator.
- SDValue ACCIn = CurDAG->getNode(MipsISD::MTLOHI, DL, MVT::Untyped,
- ADDCNode->getOperand(1),
- ADDENode->getOperand(1));
-
- // create MipsMAdd(u) node
- MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MAddu : MipsISD::MAdd;
-
- SDValue MAdd = CurDAG->getNode(MultOpc, DL, MVT::Untyped,
- MultNode->getOperand(0),// Factor 0
- MultNode->getOperand(1),// Factor 1
- ACCIn);
-
- // replace uses of adde and addc here
- if (!SDValue(ADDCNode, 0).use_empty()) {
- SDValue LoOut = CurDAG->getNode(MipsISD::MFLO, DL, MVT::i32, MAdd);
- CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDCNode, 0), LoOut);
- }
- if (!SDValue(ADDENode, 0).use_empty()) {
- SDValue HiOut = CurDAG->getNode(MipsISD::MFHI, DL, MVT::i32, MAdd);
- CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDENode, 0), HiOut);
- }
-
- return true;
-}
-
-// selectMSUB -
-// Transforms a subgraph in CurDAG if the following pattern is found:
-// (addc Lo0, multLo), (sube Hi0, multHi),
-// where,
-// multHi/Lo: product of multiplication
-// Lo0: initial value of Lo register
-// Hi0: initial value of Hi register
-// Return true if pattern matching was successful.
-static bool selectMSUB(SDNode *SUBENode, SelectionDAG *CurDAG) {
- // SUBENode's second operand must be a flag output of an SUBC node in order
- // for the matching to be successful.
- SDNode *SUBCNode = SUBENode->getOperand(2).getNode();
-
- if (SUBCNode->getOpcode() != ISD::SUBC)
- return false;
-
- SDValue MultHi = SUBENode->getOperand(1);
- SDValue MultLo = SUBCNode->getOperand(1);
- SDNode *MultNode = MultHi.getNode();
- unsigned MultOpc = MultHi.getOpcode();
-
- // MultHi and MultLo must be generated by the same node,
- if (MultLo.getNode() != MultNode)
- return false;
-
- // and it must be a multiplication.
- if (MultOpc != ISD::SMUL_LOHI && MultOpc != ISD::UMUL_LOHI)
- return false;
-
- // MultLo amd MultHi must be the first and second output of MultNode
- // respectively.
- if (MultHi.getResNo() != 1 || MultLo.getResNo() != 0)
- return false;
-
- // Transform this to a MSUB only if SUBENode and SUBCNode are the only users
- // of the values of MultNode, in which case MultNode will be removed in later
- // phases.
- // If there exist users other than SUBENode or SUBCNode, this function returns
- // here, which will result in MultNode being mapped to a single MULT
- // instruction node rather than a pair of MULT and MSUB instructions being
- // produced.
- if (!MultHi.hasOneUse() || !MultLo.hasOneUse())
- return false;
-
- SDLoc DL(SUBENode);
-
- // Initialize accumulator.
- SDValue ACCIn = CurDAG->getNode(MipsISD::MTLOHI, DL, MVT::Untyped,
- SUBCNode->getOperand(0),
- SUBENode->getOperand(0));
-
- // create MipsSub(u) node
- MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MSubu : MipsISD::MSub;
-
- SDValue MSub = CurDAG->getNode(MultOpc, DL, MVT::Glue,
- MultNode->getOperand(0),// Factor 0
- MultNode->getOperand(1),// Factor 1
- ACCIn);
-
- // replace uses of sube and subc here
- if (!SDValue(SUBCNode, 0).use_empty()) {
- SDValue LoOut = CurDAG->getNode(MipsISD::MFLO, DL, MVT::i32, MSub);
- CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBCNode, 0), LoOut);
- }
- if (!SDValue(SUBENode, 0).use_empty()) {
- SDValue HiOut = CurDAG->getNode(MipsISD::MFHI, DL, MVT::i32, MSub);
- CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBENode, 0), HiOut);
- }
-
- return true;
-}
-
-static SDValue performADDECombine(SDNode *N, SelectionDAG &DAG,
- TargetLowering::DAGCombinerInfo &DCI,
- const MipsSubtarget &Subtarget) {
- if (DCI.isBeforeLegalize())
- return SDValue();
-
- if (Subtarget.hasMips32() && !Subtarget.hasMips32r6() &&
- N->getValueType(0) == MVT::i32 && selectMADD(N, &DAG))
- return SDValue(N, 0);
-
- return SDValue();
-}
-
// Fold zero extensions into MipsISD::VEXTRACT_[SZ]EXT_ELT
//
// Performs the following transformations:
@@ -820,19 +661,6 @@ static SDValue performORCombine(SDNode *N, SelectionDAG &DAG,
return SDValue();
}
-static SDValue performSUBECombine(SDNode *N, SelectionDAG &DAG,
- TargetLowering::DAGCombinerInfo &DCI,
- const MipsSubtarget &Subtarget) {
- if (DCI.isBeforeLegalize())
- return SDValue();
-
- if (Subtarget.hasMips32() && N->getValueType(0) == MVT::i32 &&
- selectMSUB(N, &DAG))
- return SDValue(N, 0);
-
- return SDValue();
-}
-
static SDValue genConstMult(SDValue X, uint64_t C, const SDLoc &DL, EVT VT,
EVT ShiftTy, SelectionDAG &DAG) {
// Clear the upper (64 - VT.sizeInBits) bits.
@@ -1110,20 +938,17 @@ MipsSETargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const {
SDValue Val;
switch (N->getOpcode()) {
- case ISD::ADDE:
- return performADDECombine(N, DAG, DCI, Subtarget);
case ISD::AND:
Val = performANDCombine(N, DAG, DCI, Subtarget);
break;
case ISD::OR:
Val = performORCombine(N, DAG, DCI, Subtarget);
break;
- case ISD::SUBE:
- return performSUBECombine(N, DAG, DCI, Subtarget);
case ISD::MUL:
return performMULCombine(N, DAG, DCI, this);
case ISD::SHL:
- return performSHLCombine(N, DAG, DCI, Subtarget);
+ Val = performSHLCombine(N, DAG, DCI, Subtarget);
+ break;
case ISD::SRA:
return performSRACombine(N, DAG, DCI, Subtarget);
case ISD::SRL:
@@ -1432,19 +1257,22 @@ static SDValue lowerMSACopyIntr(SDValue Op, SelectionDAG &DAG, unsigned Opc) {
static SDValue lowerMSASplatZExt(SDValue Op, unsigned OpNr, SelectionDAG &DAG) {
EVT ResVecTy = Op->getValueType(0);
EVT ViaVecTy = ResVecTy;
+ bool BigEndian = !DAG.getSubtarget().getTargetTriple().isLittleEndian();
SDLoc DL(Op);
// When ResVecTy == MVT::v2i64, LaneA is the upper 32 bits of the lane and
// LaneB is the lower 32-bits. Otherwise LaneA and LaneB are alternating
// lanes.
- SDValue LaneA;
- SDValue LaneB = Op->getOperand(2);
+ SDValue LaneA = Op->getOperand(OpNr);
+ SDValue LaneB;
if (ResVecTy == MVT::v2i64) {
- LaneA = DAG.getConstant(0, DL, MVT::i32);
+ LaneB = DAG.getConstant(0, DL, MVT::i32);
ViaVecTy = MVT::v4i32;
+ if(BigEndian)
+ std::swap(LaneA, LaneB);
} else
- LaneA = LaneB;
+ LaneB = LaneA;
SDValue Ops[16] = { LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, LaneA, LaneB,
LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, LaneA, LaneB };
@@ -1452,8 +1280,11 @@ static SDValue lowerMSASplatZExt(SDValue Op, unsigned OpNr, SelectionDAG &DAG) {
SDValue Result = DAG.getBuildVector(
ViaVecTy, DL, makeArrayRef(Ops, ViaVecTy.getVectorNumElements()));
- if (ViaVecTy != ResVecTy)
- Result = DAG.getNode(ISD::BITCAST, DL, ResVecTy, Result);
+ if (ViaVecTy != ResVecTy) {
+ SDValue One = DAG.getConstant(1, DL, ViaVecTy);
+ Result = DAG.getNode(ISD::BITCAST, DL, ResVecTy,
+ DAG.getNode(ISD::AND, DL, ViaVecTy, Result, One));
+ }
return Result;
}
@@ -1546,11 +1377,24 @@ static SDValue lowerMSABinaryBitImmIntr(SDValue Op, SelectionDAG &DAG,
return DAG.getNode(Opc, DL, VecTy, Op->getOperand(1), Exp2Imm);
}
+static SDValue truncateVecElts(SDValue Op, SelectionDAG &DAG) {
+ SDLoc DL(Op);
+ EVT ResTy = Op->getValueType(0);
+ SDValue Vec = Op->getOperand(2);
+ bool BigEndian = !DAG.getSubtarget().getTargetTriple().isLittleEndian();
+ MVT ResEltTy = ResTy == MVT::v2i64 ? MVT::i64 : MVT::i32;
+ SDValue ConstValue = DAG.getConstant(Vec.getScalarValueSizeInBits() - 1,
+ DL, ResEltTy);
+ SDValue SplatVec = getBuildVectorSplat(ResTy, ConstValue, BigEndian, DAG);
+
+ return DAG.getNode(ISD::AND, DL, ResTy, Vec, SplatVec);
+}
+
static SDValue lowerMSABitClear(SDValue Op, SelectionDAG &DAG) {
EVT ResTy = Op->getValueType(0);
SDLoc DL(Op);
SDValue One = DAG.getConstant(1, DL, ResTy);
- SDValue Bit = DAG.getNode(ISD::SHL, DL, ResTy, One, Op->getOperand(2));
+ SDValue Bit = DAG.getNode(ISD::SHL, DL, ResTy, One, truncateVecElts(Op, DAG));
return DAG.getNode(ISD::AND, DL, ResTy, Op->getOperand(1),
DAG.getNOT(DL, Bit, ResTy));
@@ -1643,7 +1487,7 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,
if (Op->getConstantOperandVal(3) >= EltTy.getSizeInBits())
report_fatal_error("Immediate out of range");
APInt Mask = APInt::getHighBitsSet(EltTy.getSizeInBits(),
- Op->getConstantOperandVal(3));
+ Op->getConstantOperandVal(3) + 1);
return DAG.getNode(ISD::VSELECT, DL, VecTy,
DAG.getConstant(Mask, DL, VecTy, true),
Op->getOperand(2), Op->getOperand(1));
@@ -1658,7 +1502,7 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,
if (Op->getConstantOperandVal(3) >= EltTy.getSizeInBits())
report_fatal_error("Immediate out of range");
APInt Mask = APInt::getLowBitsSet(EltTy.getSizeInBits(),
- Op->getConstantOperandVal(3));
+ Op->getConstantOperandVal(3) + 1);
return DAG.getNode(ISD::VSELECT, DL, VecTy,
DAG.getConstant(Mask, DL, VecTy, true),
Op->getOperand(2), Op->getOperand(1));
@@ -1686,7 +1530,7 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,
return DAG.getNode(ISD::XOR, DL, VecTy, Op->getOperand(1),
DAG.getNode(ISD::SHL, DL, VecTy, One,
- Op->getOperand(2)));
+ truncateVecElts(Op, DAG)));
}
case Intrinsic::mips_bnegi_b:
case Intrinsic::mips_bnegi_h:
@@ -1722,7 +1566,7 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,
return DAG.getNode(ISD::OR, DL, VecTy, Op->getOperand(1),
DAG.getNode(ISD::SHL, DL, VecTy, One,
- Op->getOperand(2)));
+ truncateVecElts(Op, DAG)));
}
case Intrinsic::mips_bseti_b:
case Intrinsic::mips_bseti_h:
@@ -2209,7 +2053,7 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,
case Intrinsic::mips_sll_w:
case Intrinsic::mips_sll_d:
return DAG.getNode(ISD::SHL, DL, Op->getValueType(0), Op->getOperand(1),
- Op->getOperand(2));
+ truncateVecElts(Op, DAG));
case Intrinsic::mips_slli_b:
case Intrinsic::mips_slli_h:
case Intrinsic::mips_slli_w:
@@ -2239,7 +2083,7 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,
case Intrinsic::mips_sra_w:
case Intrinsic::mips_sra_d:
return DAG.getNode(ISD::SRA, DL, Op->getValueType(0), Op->getOperand(1),
- Op->getOperand(2));
+ truncateVecElts(Op, DAG));
case Intrinsic::mips_srai_b:
case Intrinsic::mips_srai_h:
case Intrinsic::mips_srai_w:
@@ -2269,7 +2113,7 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,
case Intrinsic::mips_srl_w:
case Intrinsic::mips_srl_d:
return DAG.getNode(ISD::SRL, DL, Op->getValueType(0), Op->getOperand(1),
- Op->getOperand(2));
+ truncateVecElts(Op, DAG));
case Intrinsic::mips_srli_b:
case Intrinsic::mips_srli_h:
case Intrinsic::mips_srli_w:
@@ -2529,11 +2373,10 @@ SDValue MipsSETargetLowering::lowerBUILD_VECTOR(SDValue Op,
SplatBitSize != 64)
return SDValue();
- // If the value fits into a simm10 then we can use ldi.[bhwd]
- // However, if it isn't an integer type we will have to bitcast from an
- // integer type first. Also, if there are any undefs, we must lower them
- // to defined values first.
- if (ResTy.isInteger() && !HasAnyUndefs && SplatValue.isSignedIntN(10))
+ // If the value isn't an integer type we will have to bitcast
+ // from an integer type first. Also, if there are any undefs, we must
+ // lower them to defined values first.
+ if (ResTy.isInteger() && !HasAnyUndefs)
return Op;
EVT ViaVecTy;
@@ -3577,9 +3420,17 @@ MipsSETargetLowering::emitST_F16_PSEUDO(MachineInstr &MI,
: (Subtarget.isABI_O32() ? &Mips::GPR32RegClass
: &Mips::GPR64RegClass);
const bool UsingMips32 = RC == &Mips::GPR32RegClass;
- unsigned Rs = RegInfo.createVirtualRegister(RC);
+ unsigned Rs = RegInfo.createVirtualRegister(&Mips::GPR32RegClass);
BuildMI(*BB, MI, DL, TII->get(Mips::COPY_U_H), Rs).addReg(Ws).addImm(0);
+ if(!UsingMips32) {
+ unsigned Tmp = RegInfo.createVirtualRegister(&Mips::GPR64RegClass);
+ BuildMI(*BB, MI, DL, TII->get(Mips::SUBREG_TO_REG), Tmp)
+ .addImm(0)
+ .addReg(Rs)
+ .addImm(Mips::sub_32);
+ Rs = Tmp;
+ }
BuildMI(*BB, MI, DL, TII->get(UsingMips32 ? Mips::SH : Mips::SH64))
.addReg(Rs)
.addReg(Rt)
@@ -3628,7 +3479,13 @@ MipsSETargetLowering::emitLD_F16_PSEUDO(MachineInstr &MI,
MachineInstrBuilder MIB =
BuildMI(*BB, MI, DL, TII->get(UsingMips32 ? Mips::LH : Mips::LH64), Rt);
for (unsigned i = 1; i < MI.getNumOperands(); i++)
- MIB.addOperand(MI.getOperand(i));
+ MIB.add(MI.getOperand(i));
+
+ if(!UsingMips32) {
+ unsigned Tmp = RegInfo.createVirtualRegister(&Mips::GPR32RegClass);
+ BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Tmp).addReg(Rt, 0, Mips::sub_32);
+ Rt = Tmp;
+ }
BuildMI(*BB, MI, DL, TII->get(Mips::FILL_H), Wd).addReg(Rt);
@@ -3697,6 +3554,7 @@ MipsSETargetLowering::emitFPROUND_PSEUDO(MachineInstr &MI,
assert(Subtarget.hasMSA() && Subtarget.hasMips32r2());
bool IsFGR64onMips64 = Subtarget.hasMips64() && IsFGR64;
+ bool IsFGR64onMips32 = !Subtarget.hasMips64() && IsFGR64;
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
DebugLoc DL = MI.getDebugLoc();
@@ -3707,7 +3565,9 @@ MipsSETargetLowering::emitFPROUND_PSEUDO(MachineInstr &MI,
unsigned Wtemp = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass);
const TargetRegisterClass *GPRRC =
IsFGR64onMips64 ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
- unsigned MFC1Opc = IsFGR64onMips64 ? Mips::DMFC1 : Mips::MFC1;
+ unsigned MFC1Opc = IsFGR64onMips64
+ ? Mips::DMFC1
+ : (IsFGR64onMips32 ? Mips::MFC1_D64 : Mips::MFC1);
unsigned FILLOpc = IsFGR64onMips64 ? Mips::FILL_D : Mips::FILL_W;
// Perform the register class copy as mentioned above.
@@ -3716,7 +3576,7 @@ MipsSETargetLowering::emitFPROUND_PSEUDO(MachineInstr &MI,
BuildMI(*BB, MI, DL, TII->get(FILLOpc), Wtemp).addReg(Rtemp);
unsigned WPHI = Wtemp;
- if (!Subtarget.hasMips64() && IsFGR64) {
+ if (IsFGR64onMips32) {
unsigned Rtemp2 = RegInfo.createVirtualRegister(GPRRC);
BuildMI(*BB, MI, DL, TII->get(Mips::MFHC1_D64), Rtemp2).addReg(Fs);
unsigned Wtemp2 = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass);
@@ -3810,7 +3670,9 @@ MipsSETargetLowering::emitFPEXTEND_PSEUDO(MachineInstr &MI,
MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
const TargetRegisterClass *GPRRC =
IsFGR64onMips64 ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
- unsigned MTC1Opc = IsFGR64onMips64 ? Mips::DMTC1 : Mips::MTC1;
+ unsigned MTC1Opc = IsFGR64onMips64
+ ? Mips::DMTC1
+ : (IsFGR64onMips32 ? Mips::MTC1_D64 : Mips::MTC1);
unsigned COPYOpc = IsFGR64onMips64 ? Mips::COPY_S_D : Mips::COPY_S_W;
unsigned Wtemp = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass);
diff --git a/contrib/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp b/contrib/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp
index ea703d0..ee07479 100644
--- a/contrib/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp
+++ b/contrib/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp
@@ -207,13 +207,16 @@ storeRegToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
Opc = Mips::SDC1;
else if (Mips::FGR64RegClass.hasSubClassEq(RC))
Opc = Mips::SDC164;
- else if (RC->hasType(MVT::v16i8))
+ else if (TRI->isTypeLegalForClass(*RC, MVT::v16i8))
Opc = Mips::ST_B;
- else if (RC->hasType(MVT::v8i16) || RC->hasType(MVT::v8f16))
+ else if (TRI->isTypeLegalForClass(*RC, MVT::v8i16) ||
+ TRI->isTypeLegalForClass(*RC, MVT::v8f16))
Opc = Mips::ST_H;
- else if (RC->hasType(MVT::v4i32) || RC->hasType(MVT::v4f32))
+ else if (TRI->isTypeLegalForClass(*RC, MVT::v4i32) ||
+ TRI->isTypeLegalForClass(*RC, MVT::v4f32))
Opc = Mips::ST_W;
- else if (RC->hasType(MVT::v2i64) || RC->hasType(MVT::v2f64))
+ else if (TRI->isTypeLegalForClass(*RC, MVT::v2i64) ||
+ TRI->isTypeLegalForClass(*RC, MVT::v2f64))
Opc = Mips::ST_D;
else if (Mips::LO32RegClass.hasSubClassEq(RC))
Opc = Mips::SW;
@@ -280,13 +283,16 @@ loadRegFromStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
Opc = Mips::LDC1;
else if (Mips::FGR64RegClass.hasSubClassEq(RC))
Opc = Mips::LDC164;
- else if (RC->hasType(MVT::v16i8))
+ else if (TRI->isTypeLegalForClass(*RC, MVT::v16i8))
Opc = Mips::LD_B;
- else if (RC->hasType(MVT::v8i16) || RC->hasType(MVT::v8f16))
+ else if (TRI->isTypeLegalForClass(*RC, MVT::v8i16) ||
+ TRI->isTypeLegalForClass(*RC, MVT::v8f16))
Opc = Mips::LD_H;
- else if (RC->hasType(MVT::v4i32) || RC->hasType(MVT::v4f32))
+ else if (TRI->isTypeLegalForClass(*RC, MVT::v4i32) ||
+ TRI->isTypeLegalForClass(*RC, MVT::v4f32))
Opc = Mips::LD_W;
- else if (RC->hasType(MVT::v2i64) || RC->hasType(MVT::v2f64))
+ else if (TRI->isTypeLegalForClass(*RC, MVT::v2i64) ||
+ TRI->isTypeLegalForClass(*RC, MVT::v2f64))
Opc = Mips::LD_D;
else if (Mips::HI32RegClass.hasSubClassEq(RC))
Opc = Mips::LW;
@@ -540,11 +546,20 @@ unsigned MipsSEInstrInfo::getAnalyzableBrOpc(unsigned Opc) const {
void MipsSEInstrInfo::expandRetRA(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const {
+
+ MachineInstrBuilder MIB;
if (Subtarget.isGP64bit())
- BuildMI(MBB, I, I->getDebugLoc(), get(Mips::PseudoReturn64))
- .addReg(Mips::RA_64);
+ MIB = BuildMI(MBB, I, I->getDebugLoc(), get(Mips::PseudoReturn64))
+ .addReg(Mips::RA_64, RegState::Undef);
else
- BuildMI(MBB, I, I->getDebugLoc(), get(Mips::PseudoReturn)).addReg(Mips::RA);
+ MIB = BuildMI(MBB, I, I->getDebugLoc(), get(Mips::PseudoReturn))
+ .addReg(Mips::RA, RegState::Undef);
+
+ // Retain any imp-use flags.
+ for (auto & MO : I->operands()) {
+ if (MO.isImplicit())
+ MIB.add(MO);
+ }
}
void MipsSEInstrInfo::expandERet(MachineBasicBlock &MBB,
@@ -558,8 +573,8 @@ MipsSEInstrInfo::compareOpndSize(unsigned Opc,
const MCInstrDesc &Desc = get(Opc);
assert(Desc.NumOperands == 2 && "Unary instruction expected.");
const MipsRegisterInfo *RI = &getRegisterInfo();
- unsigned DstRegSize = getRegClass(Desc, 0, RI, MF)->getSize();
- unsigned SrcRegSize = getRegClass(Desc, 1, RI, MF)->getSize();
+ unsigned DstRegSize = RI->getRegSizeInBits(*getRegClass(Desc, 0, RI, MF));
+ unsigned SrcRegSize = RI->getRegSizeInBits(*getRegClass(Desc, 1, RI, MF));
return std::make_pair(DstRegSize > SrcRegSize, DstRegSize < SrcRegSize);
}
diff --git a/contrib/llvm/lib/Target/Mips/MipsSchedule.td b/contrib/llvm/lib/Target/Mips/MipsSchedule.td
index c0de59b..c2947bb 100644
--- a/contrib/llvm/lib/Target/Mips/MipsSchedule.td
+++ b/contrib/llvm/lib/Target/Mips/MipsSchedule.td
@@ -84,6 +84,7 @@ def II_DIVU : InstrItinClass;
def II_DIV_D : InstrItinClass;
def II_DIV_S : InstrItinClass;
def II_DMFC0 : InstrItinClass;
+def II_DMT : InstrItinClass;
def II_DMTC0 : InstrItinClass;
def II_DMFC1 : InstrItinClass;
def II_DMTC1 : InstrItinClass;
@@ -113,8 +114,12 @@ def II_DSBH : InstrItinClass;
def II_DSHD : InstrItinClass;
def II_DSUBU : InstrItinClass;
def II_DSUB : InstrItinClass;
+def II_DVPE : InstrItinClass;
+def II_EMT : InstrItinClass;
+def II_EVPE : InstrItinClass;
def II_EXT : InstrItinClass; // Any EXT instruction
def II_FLOOR : InstrItinClass;
+def II_FORK : InstrItinClass;
def II_INS : InstrItinClass; // Any INS instruction
def II_IndirectBranchPseudo : InstrItinClass; // Indirect branch pseudo.
def II_J : InstrItinClass;
@@ -345,6 +350,7 @@ def II_WRPGPR : InstrItinClass;
def II_RDPGPR : InstrItinClass;
def II_DVP : InstrItinClass;
def II_EVP : InstrItinClass;
+def II_YIELD : InstrItinClass;
//===----------------------------------------------------------------------===//
// Mips Generic instruction itineraries.
@@ -386,6 +392,7 @@ def MipsGenericItineraries : ProcessorItineraries<[ALU, IMULDIV], [], [
InstrItinData<II_DCLZ , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DMOD , [InstrStage<17, [IMULDIV]>]>,
InstrItinData<II_DMODU , [InstrStage<17, [IMULDIV]>]>,
+ InstrItinData<II_DMT , [InstrStage<2, [ALU]>]>,
InstrItinData<II_DSLL , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DSLL32 , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DSRL , [InstrStage<1, [ALU]>]>,
@@ -404,7 +411,11 @@ def MipsGenericItineraries : ProcessorItineraries<[ALU, IMULDIV], [], [
InstrItinData<II_DSHD , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DCLO , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DCLZ , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_DVPE , [InstrStage<2, [ALU]>]>,
+ InstrItinData<II_EMT , [InstrStage<2, [ALU]>]>,
+ InstrItinData<II_EVPE , [InstrStage<2, [ALU]>]>,
InstrItinData<II_EXT , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_FORK , [InstrStage<1, [ALU]>]>,
InstrItinData<II_INS , [InstrStage<1, [ALU]>]>,
InstrItinData<II_LUI , [InstrStage<1, [ALU]>]>,
InstrItinData<II_MOVE , [InstrStage<1, [ALU]>]>,
@@ -670,5 +681,6 @@ def MipsGenericItineraries : ProcessorItineraries<[ALU, IMULDIV], [], [
InstrItinData<II_WRPGPR , [InstrStage<1, [ALU]>]>,
InstrItinData<II_RDPGPR , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DVP , [InstrStage<1, [ALU]>]>,
- InstrItinData<II_EVP , [InstrStage<1, [ALU]>]>
+ InstrItinData<II_EVP , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_YIELD , [InstrStage<5, [ALU]>]>
]>;
diff --git a/contrib/llvm/lib/Target/Mips/MipsScheduleGeneric.td b/contrib/llvm/lib/Target/Mips/MipsScheduleGeneric.td
index 15a0401..89cda67 100644
--- a/contrib/llvm/lib/Target/Mips/MipsScheduleGeneric.td
+++ b/contrib/llvm/lib/Target/Mips/MipsScheduleGeneric.td
@@ -187,7 +187,11 @@ def GenericIssueCOP0 : ProcResource<1> { let Super = GenericCOP0; }
def GenericWriteCOP0TLB : SchedWriteRes<[GenericIssueCOP0]> { let Latency = 4; }
def GenericWriteCOP0 : SchedWriteRes<[GenericIssueCOP0]> { let Latency = 3; }
def GenericReadCOP0 : SchedWriteRes<[GenericIssueCOP0]> { let Latency = 2; }
-def GnereicReadWritePGPR : SchedWriteRes<[GenericIssueCOP0]>;
+def GenericReadWritePGPR : SchedWriteRes<[GenericIssueCOP0]>;
+def GenericReadWriteCOP0Long : SchedWriteRes<[GenericIssueCOP0]> {
+ let Latency = 5;
+}
+def GenericWriteCOP0Short : SchedWriteRes<[GenericIssueCOP0]>;
def : ItinRW<[GenericWriteCOP0TLB], [II_TLBP, II_TLBR, II_TLBWI, II_TLBWR]>;
def : ItinRW<[GenericWriteCOP0TLB], [II_TLBINV, II_TLBINVF]>;
@@ -261,6 +265,14 @@ def : ItinRW<[GenericWriteLoad], [II_LBE, II_LBUE, II_LHE, II_LHUE, II_LWE,
def : ItinRW<[GenericWriteLoad], [II_LWLE, II_LWRE]>;
+// MIPS MT instructions
+// ====================
+
+def : ItinRW<[GenericWriteMove], [II_DMT, II_DVPE, II_EMT, II_EVPE]>;
+
+def : ItinRW<[GenericReadWriteCOP0Long], [II_YIELD]>;
+def : ItinRW<[GenericWriteCOP0Short], [II_FORK]>;
+
// MIPS32R6 and MIPS16e
// ====================
diff --git a/contrib/llvm/lib/Target/Mips/MipsScheduleP5600.td b/contrib/llvm/lib/Target/Mips/MipsScheduleP5600.td
index 882a241..fedfac2 100644
--- a/contrib/llvm/lib/Target/Mips/MipsScheduleP5600.td
+++ b/contrib/llvm/lib/Target/Mips/MipsScheduleP5600.td
@@ -19,7 +19,7 @@ def MipsP5600Model : SchedMachineModel {
HasMips64, HasMips64r2, HasCnMips,
InMicroMips, InMips16Mode,
HasMicroMips32r6, HasMicroMips64r6,
- HasDSP, HasDSPR2];
+ HasDSP, HasDSPR2, HasMT];
}
diff --git a/contrib/llvm/lib/Target/Mips/MipsSubtarget.cpp b/contrib/llvm/lib/Target/Mips/MipsSubtarget.cpp
index 3e7570f..eba21e0 100644
--- a/contrib/llvm/lib/Target/Mips/MipsSubtarget.cpp
+++ b/contrib/llvm/lib/Target/Mips/MipsSubtarget.cpp
@@ -11,10 +11,10 @@
//
//===----------------------------------------------------------------------===//
-#include "MipsMachineFunction.h"
+#include "MipsSubtarget.h"
#include "Mips.h"
+#include "MipsMachineFunction.h"
#include "MipsRegisterInfo.h"
-#include "MipsSubtarget.h"
#include "MipsTargetMachine.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/Function.h"
@@ -59,9 +59,8 @@ static cl::opt<bool>
void MipsSubtarget::anchor() { }
-MipsSubtarget::MipsSubtarget(const Triple &TT, const std::string &CPU,
- const std::string &FS, bool little,
- const MipsTargetMachine &TM)
+MipsSubtarget::MipsSubtarget(const Triple &TT, StringRef CPU, StringRef FS,
+ bool little, const MipsTargetMachine &TM)
: MipsGenSubtargetInfo(TT, CPU, FS), MipsArchVersion(MipsDefault),
IsLittle(little), IsSoftFloat(false), IsSingleFloat(false), IsFPXX(false),
NoABICalls(false), IsFP64bit(false), UseOddSPReg(true),
@@ -70,15 +69,14 @@ MipsSubtarget::MipsSubtarget(const Triple &TT, const std::string &CPU,
HasMips4_32r2(false), HasMips5_32r2(false), InMips16Mode(false),
InMips16HardFloat(Mips16HardFloat), InMicroMipsMode(false), HasDSP(false),
HasDSPR2(false), HasDSPR3(false), AllowMixed16_32(Mixed16_32 | Mips_Os16),
- Os16(Mips_Os16), HasMSA(false), UseTCCInDIV(false), HasEVA(false), TM(TM),
+ Os16(Mips_Os16), HasMSA(false), UseTCCInDIV(false), HasSym32(false),
+ HasEVA(false), DisableMadd4(false), HasMT(false), TM(TM),
TargetTriple(TT), TSInfo(),
InstrInfo(
MipsInstrInfo::create(initializeSubtargetDependencies(CPU, FS, TM))),
FrameLowering(MipsFrameLowering::create(*this)),
TLInfo(MipsTargetLowering::create(TM, *this)) {
- PreviousInMips16Mode = InMips16Mode;
-
if (MipsArchVersion == MipsDefault)
MipsArchVersion = Mips32;
@@ -117,6 +115,9 @@ MipsSubtarget::MipsSubtarget(const Triple &TT, const std::string &CPU,
if (NoABICalls && TM.isPositionIndependent())
report_fatal_error("position-independent code requires '-mabicalls'");
+ if (isABI_N64() && !TM.isPositionIndependent() && !hasSym32())
+ NoABICalls = true;
+
// Set UseSmallSection.
UseSmallSection = GPOpt;
if (!NoABICalls && GPOpt) {
diff --git a/contrib/llvm/lib/Target/Mips/MipsSubtarget.h b/contrib/llvm/lib/Target/Mips/MipsSubtarget.h
index 38d3cee..cce3b8c 100644
--- a/contrib/llvm/lib/Target/Mips/MipsSubtarget.h
+++ b/contrib/llvm/lib/Target/Mips/MipsSubtarget.h
@@ -78,7 +78,7 @@ class MipsSubtarget : public MipsGenSubtargetInfo {
// IsNan2008 - IEEE 754-2008 NaN encoding.
bool IsNaN2008bit;
- // IsFP64bit - General-purpose registers are 64 bits wide
+ // IsGP64bit - General-purpose registers are 64 bits wide
bool IsGP64bit;
// IsPTR64bit - Pointers are 64 bit wide
@@ -119,9 +119,6 @@ class MipsSubtarget : public MipsGenSubtargetInfo {
// Mips16 hard float
bool InMips16HardFloat;
- // PreviousInMips16 -- the function we just processed was in Mips 16 Mode
- bool PreviousInMips16Mode;
-
// InMicroMips -- can process MicroMips instructions
bool InMicroMipsMode;
@@ -142,8 +139,21 @@ class MipsSubtarget : public MipsGenSubtargetInfo {
// UseTCCInDIV -- Enables the use of trapping in the assembler.
bool UseTCCInDIV;
+ // Sym32 -- On Mips64 symbols are 32 bits.
+ bool HasSym32;
+
// HasEVA -- supports EVA ASE.
bool HasEVA;
+
+ // nomadd4 - disables generation of 4-operand madd.s, madd.d and
+ // related instructions.
+ bool DisableMadd4;
+
+ // HasMT -- support MT ASE.
+ bool HasMT;
+
+ // Disable use of the `jal` instruction.
+ bool UseLongCalls = false;
InstrItineraryData InstrItins;
@@ -175,8 +185,8 @@ public:
/// This constructor initializes the data members to match that
/// of the specified triple.
- MipsSubtarget(const Triple &TT, const std::string &CPU, const std::string &FS,
- bool little, const MipsTargetMachine &TM);
+ MipsSubtarget(const Triple &TT, StringRef CPU, StringRef FS, bool little,
+ const MipsTargetMachine &TM);
/// ParseSubtargetFeatures - Parses features string setting specified
/// subtarget options. Definition of function is auto generated by tblgen.
@@ -229,7 +239,11 @@ public:
unsigned getGPRSizeInBytes() const { return isGP64bit() ? 8 : 4; }
bool isPTR64bit() const { return IsPTR64bit; }
bool isPTR32bit() const { return !IsPTR64bit; }
+ bool hasSym32() const {
+ return (HasSym32 && isABI_N64()) || isABI_N32() || isABI_O32();
+ }
bool isSingleFloat() const { return IsSingleFloat; }
+ bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); }
bool hasVFPU() const { return HasVFPU; }
bool inMips16Mode() const { return InMips16Mode; }
bool inMips16ModeDefault() const {
@@ -249,13 +263,17 @@ public:
bool hasDSPR2() const { return HasDSPR2; }
bool hasDSPR3() const { return HasDSPR3; }
bool hasMSA() const { return HasMSA; }
+ bool disableMadd4() const { return DisableMadd4; }
bool hasEVA() const { return HasEVA; }
+ bool hasMT() const { return HasMT; }
bool useSmallSection() const { return UseSmallSection; }
bool hasStandardEncoding() const { return !inMips16Mode(); }
bool useSoftFloat() const { return IsSoftFloat; }
+ bool useLongCalls() const { return UseLongCalls; }
+
bool enableLongBranchPass() const {
return hasStandardEncoding() || allowMixed16_32();
}
@@ -271,6 +289,8 @@ public:
bool isTargetNaCl() const { return TargetTriple.isOSNaCl(); }
+ bool isXRaySupported() const override { return true; }
+
// for now constant islands are on for the whole compilation unit but we only
// really use them if in addition we are in mips16 mode
static bool useConstantIslands();
diff --git a/contrib/llvm/lib/Target/Mips/MipsTargetMachine.cpp b/contrib/llvm/lib/Target/Mips/MipsTargetMachine.cpp
index bb48188..330ae19 100644
--- a/contrib/llvm/lib/Target/Mips/MipsTargetMachine.cpp
+++ b/contrib/llvm/lib/Target/Mips/MipsTargetMachine.cpp
@@ -12,26 +12,29 @@
//===----------------------------------------------------------------------===//
#include "MipsTargetMachine.h"
+#include "MCTargetDesc/MipsABIInfo.h"
+#include "MCTargetDesc/MipsMCTargetDesc.h"
#include "Mips.h"
-#include "Mips16FrameLowering.h"
#include "Mips16ISelDAGToDAG.h"
-#include "Mips16ISelLowering.h"
-#include "Mips16InstrInfo.h"
-#include "MipsFrameLowering.h"
-#include "MipsInstrInfo.h"
-#include "MipsSEFrameLowering.h"
#include "MipsSEISelDAGToDAG.h"
-#include "MipsSEISelLowering.h"
-#include "MipsSEInstrInfo.h"
+#include "MipsSubtarget.h"
#include "MipsTargetObjectFile.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/CodeGen/BasicTTIImpl.h"
+#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/TargetPassConfig.h"
-#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/IR/Attributes.h"
+#include "llvm/IR/Function.h"
+#include "llvm/Support/CodeGen.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Transforms/Scalar.h"
+#include "llvm/Target/TargetOptions.h"
+#include <string>
using namespace llvm;
@@ -48,7 +51,7 @@ extern "C" void LLVMInitializeMipsTarget() {
static std::string computeDataLayout(const Triple &TT, StringRef CPU,
const TargetOptions &Options,
bool isLittle) {
- std::string Ret = "";
+ std::string Ret;
MipsABIInfo ABI = MipsABIInfo::computeTargetABI(TT, CPU, Options.MCOptions);
// There are both little and big endian mips.
@@ -102,7 +105,7 @@ MipsTargetMachine::MipsTargetMachine(const Target &T, const Triple &TT,
: LLVMTargetMachine(T, computeDataLayout(TT, CPU, Options, isLittle), TT,
CPU, FS, Options, getEffectiveRelocModel(CM, RM), CM,
OL),
- isLittle(isLittle), TLOF(make_unique<MipsTargetObjectFile>()),
+ isLittle(isLittle), TLOF(llvm::make_unique<MipsTargetObjectFile>()),
ABI(MipsABIInfo::computeTargetABI(TT, CPU, Options.MCOptions)),
Subtarget(nullptr), DefaultSubtarget(TT, CPU, FS, isLittle, *this),
NoMips16Subtarget(TT, CPU, FS.empty() ? "-mips16" : FS.str() + ",-mips16",
@@ -113,9 +116,9 @@ MipsTargetMachine::MipsTargetMachine(const Target &T, const Triple &TT,
initAsmInfo();
}
-MipsTargetMachine::~MipsTargetMachine() {}
+MipsTargetMachine::~MipsTargetMachine() = default;
-void MipsebTargetMachine::anchor() { }
+void MipsebTargetMachine::anchor() {}
MipsebTargetMachine::MipsebTargetMachine(const Target &T, const Triple &TT,
StringRef CPU, StringRef FS,
@@ -125,7 +128,7 @@ MipsebTargetMachine::MipsebTargetMachine(const Target &T, const Triple &TT,
CodeGenOpt::Level OL)
: MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}
-void MipselTargetMachine::anchor() { }
+void MipselTargetMachine::anchor() {}
MipselTargetMachine::MipselTargetMachine(const Target &T, const Triple &TT,
StringRef CPU, StringRef FS,
@@ -151,6 +154,11 @@ MipsTargetMachine::getSubtargetImpl(const Function &F) const {
bool hasNoMips16Attr =
!F.getFnAttribute("nomips16").hasAttribute(Attribute::None);
+ bool HasMicroMipsAttr =
+ !F.getFnAttribute("micromips").hasAttribute(Attribute::None);
+ bool HasNoMicroMipsAttr =
+ !F.getFnAttribute("nomicromips").hasAttribute(Attribute::None);
+
// FIXME: This is related to the code below to reset the target options,
// we need to know whether or not the soft float flag is set on the
// function, so we can enable it as a subtarget feature.
@@ -162,6 +170,10 @@ MipsTargetMachine::getSubtargetImpl(const Function &F) const {
FS += FS.empty() ? "+mips16" : ",+mips16";
else if (hasNoMips16Attr)
FS += FS.empty() ? "-mips16" : ",-mips16";
+ if (HasMicroMipsAttr)
+ FS += FS.empty() ? "+micromips" : ",+micromips";
+ else if (HasNoMicroMipsAttr)
+ FS += FS.empty() ? "-micromips" : ",-micromips";
if (softFloat)
FS += FS.empty() ? "+soft-float" : ",+soft-float";
@@ -182,14 +194,14 @@ void MipsTargetMachine::resetSubtarget(MachineFunction *MF) {
Subtarget = const_cast<MipsSubtarget *>(getSubtargetImpl(*MF->getFunction()));
MF->setSubtarget(Subtarget);
- return;
}
namespace {
+
/// Mips Code Generator Pass Configuration Options.
class MipsPassConfig : public TargetPassConfig {
public:
- MipsPassConfig(MipsTargetMachine *TM, PassManagerBase &PM)
+ MipsPassConfig(MipsTargetMachine &TM, PassManagerBase &PM)
: TargetPassConfig(TM, PM) {
// The current implementation of long branch pass requires a scratch
// register ($at) to be available before branch instructions. Tail merging
@@ -209,35 +221,34 @@ public:
void addIRPasses() override;
bool addInstSelector() override;
void addPreEmitPass() override;
-
void addPreRegAlloc() override;
-
};
-} // namespace
+
+} // end anonymous namespace
TargetPassConfig *MipsTargetMachine::createPassConfig(PassManagerBase &PM) {
- return new MipsPassConfig(this, PM);
+ return new MipsPassConfig(*this, PM);
}
void MipsPassConfig::addIRPasses() {
TargetPassConfig::addIRPasses();
- addPass(createAtomicExpandPass(&getMipsTargetMachine()));
+ addPass(createAtomicExpandPass());
if (getMipsSubtarget().os16())
- addPass(createMipsOs16Pass(getMipsTargetMachine()));
+ addPass(createMipsOs16Pass());
if (getMipsSubtarget().inMips16HardFloat())
- addPass(createMips16HardFloatPass(getMipsTargetMachine()));
+ addPass(createMips16HardFloatPass());
}
// Install an instruction selector pass using
// the ISelDag to gen Mips code.
bool MipsPassConfig::addInstSelector() {
- addPass(createMipsModuleISelDagPass(getMipsTargetMachine()));
+ addPass(createMipsModuleISelDagPass());
addPass(createMips16ISelDag(getMipsTargetMachine(), getOptLevel()));
addPass(createMipsSEISelDag(getMipsTargetMachine(), getOptLevel()));
return false;
}
void MipsPassConfig::addPreRegAlloc() {
- addPass(createMipsOptimizePICCallPass(getMipsTargetMachine()));
+ addPass(createMipsOptimizePICCallPass());
}
TargetIRAnalysis MipsTargetMachine::getTargetIRAnalysis() {
@@ -257,14 +268,14 @@ TargetIRAnalysis MipsTargetMachine::getTargetIRAnalysis() {
// machine code is emitted. return true if -print-machineinstrs should
// print out the code after the passes.
void MipsPassConfig::addPreEmitPass() {
- MipsTargetMachine &TM = getMipsTargetMachine();
+ addPass(createMicroMipsSizeReductionPass());
// The delay slot filler pass can potientially create forbidden slot (FS)
// hazards for MIPSR6 which the hazard schedule pass (HSP) will fix. Any
// (new) pass that creates compact branches after the HSP must handle FS
// hazards itself or be pipelined before the HSP.
- addPass(createMipsDelaySlotFillerPass(TM));
+ addPass(createMipsDelaySlotFillerPass());
addPass(createMipsHazardSchedule());
- addPass(createMipsLongBranchPass(TM));
+ addPass(createMipsLongBranchPass());
addPass(createMipsConstantIslandPass());
}
diff --git a/contrib/llvm/lib/Target/Mips/MipsTargetMachine.h b/contrib/llvm/lib/Target/Mips/MipsTargetMachine.h
index e4cf17e..a346286 100644
--- a/contrib/llvm/lib/Target/Mips/MipsTargetMachine.h
+++ b/contrib/llvm/lib/Target/Mips/MipsTargetMachine.h
@@ -1,4 +1,4 @@
-//===-- MipsTargetMachine.h - Define TargetMachine for Mips -----*- C++ -*-===//
+//===- MipsTargetMachine.h - Define TargetMachine for Mips ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,15 +16,14 @@
#include "MCTargetDesc/MipsABIInfo.h"
#include "MipsSubtarget.h"
-#include "llvm/CodeGen/BasicTTIImpl.h"
-#include "llvm/CodeGen/Passes.h"
-#include "llvm/CodeGen/SelectionDAGISel.h"
-#include "llvm/Target/TargetFrameLowering.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/CodeGen.h"
#include "llvm/Target/TargetMachine.h"
+#include <memory>
namespace llvm {
-class formatted_raw_ostream;
-class MipsRegisterInfo;
class MipsTargetMachine : public LLVMTargetMachine {
bool isLittle;
@@ -67,12 +66,17 @@ public:
bool isLittleEndian() const { return isLittle; }
const MipsABIInfo &getABI() const { return ABI; }
+
+ bool isMachineVerifierClean() const override {
+ return false;
+ }
};
/// Mips32/64 big endian target machine.
///
class MipsebTargetMachine : public MipsTargetMachine {
virtual void anchor();
+
public:
MipsebTargetMachine(const Target &T, const Triple &TT, StringRef CPU,
StringRef FS, const TargetOptions &Options,
@@ -84,6 +88,7 @@ public:
///
class MipselTargetMachine : public MipsTargetMachine {
virtual void anchor();
+
public:
MipselTargetMachine(const Target &T, const Triple &TT, StringRef CPU,
StringRef FS, const TargetOptions &Options,
@@ -91,6 +96,6 @@ public:
CodeGenOpt::Level OL);
};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_LIB_TARGET_MIPS_MIPSTARGETMACHINE_H
diff --git a/contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.cpp b/contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.cpp
index c5d6a05..4d73c39 100644
--- a/contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.cpp
+++ b/contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.cpp
@@ -10,13 +10,13 @@
#include "MipsTargetObjectFile.h"
#include "MipsSubtarget.h"
#include "MipsTargetMachine.h"
+#include "llvm/BinaryFormat/ELF.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/ELF.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;
diff --git a/contrib/llvm/lib/Target/Mips/MipsTargetStreamer.h b/contrib/llvm/lib/Target/Mips/MipsTargetStreamer.h
index 41ebe41..7d9f99c 100644
--- a/contrib/llvm/lib/Target/Mips/MipsTargetStreamer.h
+++ b/contrib/llvm/lib/Target/Mips/MipsTargetStreamer.h
@@ -40,6 +40,8 @@ public:
virtual void emitDirectiveSetNoMacro();
virtual void emitDirectiveSetMsa();
virtual void emitDirectiveSetNoMsa();
+ virtual void emitDirectiveSetMt();
+ virtual void emitDirectiveSetNoMt();
virtual void emitDirectiveSetAt();
virtual void emitDirectiveSetAtWithArg(unsigned RegNo);
virtual void emitDirectiveSetNoAt();
@@ -96,6 +98,7 @@ public:
virtual void emitDirectiveModuleOddSPReg();
virtual void emitDirectiveModuleSoftFloat();
virtual void emitDirectiveModuleHardFloat();
+ virtual void emitDirectiveModuleMT();
virtual void emitDirectiveSetFp(MipsABIFlagsSection::FpABIKind Value);
virtual void emitDirectiveSetOddSPReg();
virtual void emitDirectiveSetNoOddSPReg();
@@ -204,6 +207,8 @@ public:
void emitDirectiveSetNoMacro() override;
void emitDirectiveSetMsa() override;
void emitDirectiveSetNoMsa() override;
+ void emitDirectiveSetMt() override;
+ void emitDirectiveSetNoMt() override;
void emitDirectiveSetAt() override;
void emitDirectiveSetAtWithArg(unsigned RegNo) override;
void emitDirectiveSetNoAt() override;
@@ -267,6 +272,7 @@ public:
void emitDirectiveModuleOddSPReg() override;
void emitDirectiveModuleSoftFloat() override;
void emitDirectiveModuleHardFloat() override;
+ void emitDirectiveModuleMT() override;
void emitDirectiveSetFp(MipsABIFlagsSection::FpABIKind Value) override;
void emitDirectiveSetOddSPReg() override;
void emitDirectiveSetNoOddSPReg() override;
diff --git a/contrib/llvm/lib/Target/Mips/Relocation.txt b/contrib/llvm/lib/Target/Mips/Relocation.txt
new file mode 100644
index 0000000..f1a6fd8
--- /dev/null
+++ b/contrib/llvm/lib/Target/Mips/Relocation.txt
@@ -0,0 +1,125 @@
+MIPS Relocation Principles
+
+In LLVM, there are several elements of the llvm::ISD::NodeType enum
+that deal with addresses and/or relocations. These are defined in
+include/llvm/Target/TargetSelectionDAG.td, namely:
+ GlobalAddress, GlobalTLSAddress, JumpTable, ConstantPool,
+ ExternalSymbol, BlockAddress
+The MIPS backend uses several principles to handle these.
+
+1. Code for lowering addresses references to machine dependent code is
+factored into common code for generating different address forms and
+is called by the relocation model specific lowering function, using
+templated functions. For example:
+
+ // lib/Target/Mips/MipsISelLowering.cpp
+ SDValue MipsTargetLowering::
+ lowerJumpTable(SDValue Op, SelectionDAG &DAG) const
+
+calls
+
+ template <class NodeTy> // lib/Target/Mips/MipsISelLowering.h
+ SDValue getAddrLocal(NodeTy *N, const SDLoc &DL, EVT Ty,
+ SelectionDAG &DAG, bool IsN32OrN64) const
+
+which calls the overloaded function:
+
+ // lib/Target/Mips/MipsISelLowering.h
+ SDValue getTargetNode(JumpTableSDNode *N, EVT Ty, SelectionDAG &DAG,
+ unsigned Flag) const;
+
+2. Generic address nodes are lowered to some combination of target
+independent and machine specific SDNodes (for example:
+MipsISD::{Highest, Higher, Hi, Lo}) depending upon relocation model,
+ABI, and compilation options.
+
+The choice of specific instructions that are to be used is delegated
+to ISel which in turn relies on TableGen patterns to choose subtarget
+specific instructions. For example, in getAddrLocal, the pseudo-code
+generated is:
+
+ (add (load (wrapper $gp, %got(sym)), %lo(sym))
+
+where "%lo" represents an instance of an SDNode with opcode
+"MipsISD::Lo", "wrapper" indicates one with opcode "MipsISD::Wrapper",
+and "%got" the global table pointer "getGlobalReg(...)". The "add" is
+"ISD::ADD", not a target dependent one.
+
+3. A TableGen multiclass pattern "MipsHiLoRelocs" is used to define a
+template pattern parameterized over the load upper immediate
+instruction, add operation, the zero register, and register class.
+Here the instantiation of MipsHiLoRelocs in MipsInstrInfo.td is used
+to MIPS32 to compute addresses for the static relocation model.
+
+ // lib/Target/Mips/MipsInstrInfo.td
+ multiclass MipsHiLoRelocs<Instruction Lui, Instruction Addiu,
+ Register ZeroReg, RegisterOperand GPROpnd> {
+ def : MipsPat<(MipsHi tglobaladdr:$in), (Lui tglobaladdr:$in)>;
+ ...
+ def : MipsPat<(MipsLo tglobaladdr:$in), (Addiu ZeroReg, tglobaladdr:$in)>;
+ ...
+ def : MipsPat<(add GPROpnd:$hi, (MipsLo tglobaladdr:$lo)),
+ (Addiu GPROpnd:$hi, tglobaladdr:$lo)>;
+ ...
+ }
+ defm : MipsHiLoRelocs<LUi, ADDiu, ZERO, GPR32Opnd>;
+
+ // lib/Target/Mips/Mips64InstrInfo.td
+ defm : MipsHiLoRelocs<LUi64, DADDiu, ZERO_64, GPR64Opnd>, SYM_32;
+
+The instantiation in Mips64InstrInfo.td is used for MIPS64 in ILP32
+mode, as guarded by the predicate "SYM_32" and also for a submode of
+LP64 where symbols are assumed to be 32 bits wide. A similar
+multiclass for MIPS64 in LP64 mode is also defined:
+
+ // lib/Target/Mips/Mips64InstrInfo.td
+ multiclass MipsHighestHigherHiLoRelocs<Instruction Lui,
+ Instruction Daddiu> {
+ ...
+ def : MipsPat<(MipsHighest (i64 tglobaladdr:$in)),
+ (Lui tglobaladdr:$in)>;
+ ...
+ def : MipsPat<(MipsHigher (i64 tglobaladdr:$in)),
+ (Daddiu ZERO_64, tglobaladdr:$in)>;
+ ...
+ def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tglobaladdr:$lo))),
+ (Daddiu GPR64:$hi, tglobaladdr:$lo)>;
+ ...
+ def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tglobaladdr:$lo))),
+ (Daddiu GPR64:$hi, tglobaladdr:$lo)>;
+ ...
+ def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tglobaladdr:$lo))),
+ (Daddiu GPR64:$hi, tglobaladdr:$lo)>;
+ }
+
+and it is instantiated twice:
+
+ // lib/Target/Mips/Mips64InstrInfo.td
+ defm : MipsHighestHigherHiLoRelocs<LUi64, DADDiu>, SYM_64;
+ // lib/Target/Mips/MicroMips64r6InstrInfo.td
+ defm : MipsHighestHigherHiLoRelocs<LUi64, DADDIU_MM64R6>, SYM_64,
+ ISA_MICROMIPS64R6;
+
+These patterns are used during instruction selection to match
+MipsISD::{Highest, Higher, Hi, Lo} to a specific machine instruction
+and operands.
+
+More details on how multiclasses in TableGen work can be found in the
+section "Multiclass definitions and instances" in the document
+"TableGen Language Introduction"
+
+4. Instruction definitions are multiply defined to cover the different
+register classes. In some cases, such as LW/LW64, this also accounts
+for the difference in the results of instruction execution. On MIPS32,
+"lw" loads a 32 bit value from memory. On MIPS64, "lw" loads a 32 bit
+value from memory and sign extends the value to 64 bits.
+
+ // lib/Target/Mips/MipsInstrInfo.td
+ def LUi : MMRel, LoadUpper<"lui", GPR32Opnd, uimm16_relaxed>, LUI_FM;
+ // lib/Target/Mips/Mips64InstrInfo.td
+ def LUi64 : LoadUpper<"lui", GPR64Opnd, uimm16_64_relaxed>, LUI_FM;
+
+defines two names "LUi" and "LUi64" with two different register
+classes, but with the same encoding---"LUI_FM". These instructions load a
+16-bit immediate into bits 31-16 and clear the lower 15 bits. On MIPS64,
+the result is sign-extended to 64 bits.
OpenPOWER on IntegriCloud