summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
authorSimon Dardis <simon.dardis@imgtec.com>2016-09-27 12:25:15 +0000
committerSimon Dardis <simon.dardis@imgtec.com>2016-09-27 12:25:15 +0000
commit0486d585c59a993e5d2dfffe18b487e1886ac853 (patch)
treeb9f889a384ff252ea20079f4221716a84123f9c2 /llvm/lib/Target
parent7482e596d5e09d679b239b7e1a624f197bdabf22 (diff)
downloadbcm5719-llvm-0486d585c59a993e5d2dfffe18b487e1886ac853.tar.gz
bcm5719-llvm-0486d585c59a993e5d2dfffe18b487e1886ac853.zip
[mips] Add rsqrt, recip for MIPS
Add rsqrt.[ds], recip.[ds] for MIPS. Correct the microMIPS definitions for architecture support and register usage. Reviewers: vkalintiris, zoran.jovanoic Differential Review: https://reviews.llvm.org/D24499 llvm-svn: 282485
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp12
-rw-r--r--llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td19
-rw-r--r--llvm/lib/Target/Mips/MicroMipsInstrFPU.td10
-rw-r--r--llvm/lib/Target/Mips/MipsInstrFPU.td10
-rw-r--r--llvm/lib/Target/Mips/MipsInstrInfo.td36
-rw-r--r--llvm/lib/Target/Mips/MipsSchedule.td8
-rw-r--r--llvm/lib/Target/Mips/MipsScheduleGeneric.td4
-rw-r--r--llvm/lib/Target/Mips/MipsScheduleP5600.td3
8 files changed, 77 insertions, 25 deletions
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index 58562f99d5f..e4b2a40fba6 100644
--- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -995,7 +995,7 @@ public:
void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
uint64_t Imm = getConstantImm() - Offset;
- Imm &= (1 << Bits) - 1;
+ Imm &= (1ULL << Bits) - 1;
Imm += Offset;
Imm += AdjustOffset;
Inst.addOperand(MCOperand::createImm(Imm));
@@ -1093,7 +1093,8 @@ public:
bool isRegIdx() const { return Kind == k_RegisterIndex; }
bool isImm() const override { return Kind == k_Immediate; }
bool isConstantImm() const {
- return isImm() && isa<MCConstantExpr>(getImm());
+ int64_t Res;
+ return isImm() && getImm()->evaluateAsAbsolute(Res);
}
bool isConstantImmz() const {
return isConstantImm() && getConstantImm() == 0;
@@ -1264,7 +1265,9 @@ public:
int64_t getConstantImm() const {
const MCExpr *Val = getImm();
- return static_cast<const MCConstantExpr *>(Val)->getValue();
+ int64_t Value = 0;
+ (void)Val->evaluateAsAbsolute(Value);
+ return Value;
}
MipsOperand *getMemBase() const {
@@ -4051,6 +4054,9 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_SImm32_Relaxed:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 32-bit signed immediate");
+ case Match_UImm32_Coerced:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected 32-bit immediate");
case Match_MemSImm9:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected memory with 9-bit signed offset");
diff --git a/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td b/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td
index b8d8aa0ce20..d1c2079f06a 100644
--- a/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td
+++ b/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td
@@ -186,8 +186,6 @@ class TRUNC_W_S_MMR6_ENC : POOL32F_MATH_FM_MMR6<"trunc.w.s", 0, 0b10101100>;
class TRUNC_W_D_MMR6_ENC : POOL32F_MATH_FM_MMR6<"trunc.w.d", 1, 0b10101100>;
class SQRT_S_MMR6_ENC : POOL32F_MATH_FM_MMR6<"sqrt.s", 0, 0b00101000>;
class SQRT_D_MMR6_ENC : POOL32F_MATH_FM_MMR6<"sqrt.d", 1, 0b00101000>;
-class RSQRT_S_MMR6_ENC : POOL32F_MATH_FM_MMR6<"rsqrt.s", 0, 0b00001000>;
-class RSQRT_D_MMR6_ENC : POOL32F_MATH_FM_MMR6<"rsqrt.d", 1, 0b00001000>;
class SB_MMR6_ENC : SB32_SH32_STORE_FM_MMR6<0b000110>;
class SBE_MMR6_ENC : POOL32C_STORE_EVA_FM_MMR6<0b100>;
class SCE_MMR6_ENC : POOL32C_STORE_EVA_FM_MMR6<0b110>;
@@ -198,8 +196,6 @@ class LWE_MMR6_ENC : LOAD_WORD_EVA_FM_MMR6<0b111>;
class LW_MMR6_ENC : LOAD_WORD_FM_MMR6;
class LUI_MMR6_ENC : LOAD_UPPER_IMM_FM_MMR6;
class JALRC_HB_MMR6_ENC : POOL32A_JALRC_FM_MMR6<"jalrc.hb", 0b0001111100>;
-class RECIP_S_MMR6_ENC : POOL32F_RECIP_ROUND_FM_MMR6<"recip.s", 0, 0b01001000>;
-class RECIP_D_MMR6_ENC : POOL32F_RECIP_ROUND_FM_MMR6<"recip.d", 1, 0b01001000>;
class RINT_S_MMR6_ENC : POOL32F_RINT_FM_MMR6<"rint.s", 0>;
class RINT_D_MMR6_ENC : POOL32F_RINT_FM_MMR6<"rint.d", 1>;
class ROUND_L_S_MMR6_ENC : POOL32F_RECIP_ROUND_FM_MMR6<"round.l.s", 0,
@@ -1118,14 +1114,6 @@ class SQRT_S_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"sqrt.s", FGR32Opnd, FGR32Opnd,
II_SQRT_S, fsqrt>;
class SQRT_D_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"sqrt.d", AFGR64Opnd, AFGR64Opnd,
II_SQRT_D, fsqrt>;
-class RSQRT_S_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"rsqrt.s", FGR32Opnd,
- FGR32Opnd, II_TRUNC>;
-class RSQRT_D_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"rsqrt.d", FGR32Opnd,
- AFGR64Opnd, II_TRUNC>;
-class RECIP_S_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"recip.s", FGR32Opnd,
- FGR32Opnd, II_ROUND>;
-class RECIP_D_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"recip.d", FGR32Opnd, FGR32Opnd,
- II_ROUND>;
class ROUND_L_S_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"round.l.s", FGR64Opnd,
FGR32Opnd, II_ROUND>;
class ROUND_L_D_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"round.l.d", FGR64Opnd,
@@ -1664,10 +1652,6 @@ def SQRT_S_MMR6 : StdMMR6Rel, SQRT_S_MMR6_ENC, SQRT_S_MMR6_DESC,
ISA_MICROMIPS32R6;
def SQRT_D_MMR6 : StdMMR6Rel, SQRT_D_MMR6_ENC, SQRT_D_MMR6_DESC,
ISA_MICROMIPS32R6;
-def RSQRT_S_MMR6 : StdMMR6Rel, RSQRT_S_MMR6_ENC, RSQRT_S_MMR6_DESC,
- ISA_MICROMIPS32R6;
-def RSQRT_D_MMR6 : StdMMR6Rel, RSQRT_D_MMR6_ENC, RSQRT_D_MMR6_DESC,
- ISA_MICROMIPS32R6;
def SB_MMR6 : StdMMR6Rel, SB_MMR6_DESC, SB_MMR6_ENC, ISA_MICROMIPS32R6;
def SBE_MMR6 : StdMMR6Rel, SBE_MMR6_DESC, SBE_MMR6_ENC, ISA_MICROMIPS32R6;
def SCE_MMR6 : StdMMR6Rel, SCE_MMR6_DESC, SCE_MMR6_ENC, ISA_MICROMIPS32R6;
@@ -1708,9 +1692,6 @@ def JALRC_HB_MMR6 : R6MMR6Rel, JALRC_HB_MMR6_ENC, JALRC_HB_MMR6_DESC,
def EXT_MMR6 : StdMMR6Rel, EXT_MMR6_ENC, EXT_MMR6_DESC, ISA_MICROMIPS32R6;
def INS_MMR6 : StdMMR6Rel, INS_MMR6_ENC, INS_MMR6_DESC, ISA_MICROMIPS32R6;
def JALRC_MMR6 : R6MMR6Rel, JALRC_MMR6_ENC, JALRC_MMR6_DESC, ISA_MICROMIPS32R6;
-def RECIP_S_MMR6 : StdMMR6Rel, RECIP_S_MMR6_ENC, RECIP_S_MMR6_DESC,
- ISA_MICROMIPS32R6;
-def RECIP_D_MMR6 : StdMMR6Rel, RECIP_D_MMR6_ENC, RECIP_D_MMR6_DESC, ISA_MICROMIPS32R6;
def RINT_S_MMR6 : StdMMR6Rel, RINT_S_MMR6_ENC, RINT_S_MMR6_DESC,
ISA_MICROMIPS32R6;
def RINT_D_MMR6 : StdMMR6Rel, RINT_D_MMR6_ENC, RINT_D_MMR6_DESC, ISA_MICROMIPS32R6;
diff --git a/llvm/lib/Target/Mips/MicroMipsInstrFPU.td b/llvm/lib/Target/Mips/MicroMipsInstrFPU.td
index ed92265e47f..fc83761e409 100644
--- a/llvm/lib/Target/Mips/MicroMipsInstrFPU.td
+++ b/llvm/lib/Target/Mips/MicroMipsInstrFPU.td
@@ -141,6 +141,16 @@ let AdditionalPredicates = [InMicroMips] in {
MFC1_FM_MM<0x40>;
def CTC1_MM : MMRel, MTC1_FT<"ctc1", CCROpnd, GPR32Opnd, II_CTC1>,
MFC1_FM_MM<0x60>;
+ def RECIP_S_MM : MMRel, ABSS_FT<"recip.s", FGR32Opnd, FGR32Opnd,
+ II_RECIP_S>,
+ ROUND_W_FM_MM<0b0, 0b01001000>;
+ def RECIP_D_MM : MMRel, ABSS_FT<"recip.d", AFGR64Opnd, AFGR64Opnd,
+ II_RECIP_D>, ROUND_W_FM_MM<0b1, 0b01001000>;
+ def RSQRT_S_MM : MMRel, ABSS_FT<"rsqrt.s", FGR32Opnd, FGR32Opnd,
+ II_RECIP_S>,
+ ROUND_W_FM_MM<0b0, 0b00001000>;
+ def RSQRT_D_MM : MMRel, ABSS_FT<"rsqrt.d", AFGR64Opnd, AFGR64Opnd,
+ II_RECIP_D>, ROUND_W_FM_MM<0b1, 0b00001000>;
}
let DecoderNamespace = "MicroMips", DecoderMethod = "DecodeFMemMMR2" in {
def LDC1_MM : MMRel, LW_FT<"ldc1", AFGR64Opnd, mem_mm_16, II_LDC1, load>,
diff --git a/llvm/lib/Target/Mips/MipsInstrFPU.td b/llvm/lib/Target/Mips/MipsInstrFPU.td
index 6bbbd51a638..ab7aa9dcdca 100644
--- a/llvm/lib/Target/Mips/MipsInstrFPU.td
+++ b/llvm/lib/Target/Mips/MipsInstrFPU.td
@@ -284,6 +284,16 @@ defm CEIL_W : ROUND_M<"ceil.w.d", II_CEIL>, ABSS_FM<0xe, 17>, ISA_MIPS2;
defm FLOOR_W : ROUND_M<"floor.w.d", II_FLOOR>, ABSS_FM<0xf, 17>, ISA_MIPS2;
defm CVT_W : ROUND_M<"cvt.w.d", II_CVT>, ABSS_FM<0x24, 17>;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def RECIP_S : MMRel, ABSS_FT<"recip.s", FGR32Opnd, FGR32Opnd, II_RECIP_S>,
+ ABSS_FM<0b010101, 0x10>, INSN_MIPS4_32R2;
+ def RECIP_D : MMRel, ABSS_FT<"recip.d", FGR64Opnd, FGR64Opnd, II_RECIP_D>,
+ ABSS_FM<0b010101, 0x11>, INSN_MIPS4_32R2;
+ def RSQRT_S : MMRel, ABSS_FT<"rsqrt.s", FGR32Opnd, FGR32Opnd, II_RSQRT_S>,
+ ABSS_FM<0b010110, 0x10>, INSN_MIPS4_32R2;
+ def RSQRT_D : MMRel, ABSS_FT<"rsqrt.d", FGR64Opnd, FGR64Opnd, II_RSQRT_D>,
+ ABSS_FM<0b010110, 0x11>, INSN_MIPS4_32R2;
+}
let DecoderNamespace = "Mips64" in {
let AdditionalPredicates = [NotInMicroMips] in {
def ROUND_L_S : ABSS_FT<"round.l.s", FGR64Opnd, FGR32Opnd, II_ROUND>,
diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.td b/llvm/lib/Target/Mips/MipsInstrInfo.td
index 39b31074608..3f3885443f7 100644
--- a/llvm/lib/Target/Mips/MipsInstrInfo.td
+++ b/llvm/lib/Target/Mips/MipsInstrInfo.td
@@ -300,6 +300,9 @@ class INSN_MIPS3_32_NOT_32R6_64R6 {
// The portions of MIPS-III that were also added to MIPS32
class INSN_MIPS3_32R2 { list<Predicate> InsnPredicates = [HasMips3_32r2]; }
+// The portions of MIPS-IV that were also added to MIPS32.
+class INSN_MIPS4_32 { list <Predicate> InsnPredicates = [HasMips4_32]; }
+
// The portions of MIPS-IV that were also added to MIPS32 but were removed in
// MIPS32r6 and MIPS64r6.
class INSN_MIPS4_32_NOT_32R6_64R6 {
@@ -312,6 +315,11 @@ class INSN_MIPS4_32R2_NOT_32R6_64R6 {
list<Predicate> InsnPredicates = [HasMips4_32r2, NotMips32r6, NotMips64r6];
}
+// The portions of MIPS-IV that were also added to MIPS32r2.
+class INSN_MIPS4_32R2 {
+ list<Predicate> InsnPredicates = [HasMips4_32r2];
+}
+
// The portions of MIPS-V that were also added to MIPS32r2 but were removed in
// MIPS32r6 and MIPS64r6.
class INSN_MIPS5_32R2_NOT_32R6_64R6 {
@@ -459,6 +467,16 @@ class UImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = []>
let DiagnosticType = "UImm" # Bits;
}
+// Generic case - only to support certain assembly pseudo instructions.
+class UImmAnyAsmOperandClass<int Bits, list<AsmOperandClass> Supers = []>
+ : AsmOperandClass {
+ let Name = "ImmAny";
+ let RenderMethod = "addConstantUImmOperands<32>";
+ let PredicateMethod = "isSImm<" # Bits # ">";
+ let SuperClasses = Supers;
+ let DiagnosticType = "ImmAny";
+}
+
// AsmOperandClasses require a strict ordering which is difficult to manage
// as a hierarchy. Instead, we use a linear ordering and impose an order that
// is in some places arbitrary.
@@ -482,8 +500,13 @@ class UImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = []>
// uimm5 < uimm5_64, and uimm5 < vsplat_uimm5
// This is entirely arbitrary. We need an ordering and what we pick is
// unimportant since only one is possible for a given mnemonic.
+
+def UImm32CoercedAsmOperandClass : UImmAnyAsmOperandClass<33, []> {
+ let Name = "UImm32_Coerced";
+ let DiagnosticType = "UImm32_Coerced";
+}
def SImm32RelaxedAsmOperandClass
- : SImmAsmOperandClass<32, []> {
+ : SImmAsmOperandClass<32, [UImm32CoercedAsmOperandClass]> {
let Name = "SImm32_Relaxed";
let PredicateMethod = "isAnyImm<32>";
let DiagnosticType = "SImm32_Relaxed";
@@ -507,6 +530,8 @@ def UImm16RelaxedAsmOperandClass
let PredicateMethod = "isAnyImm<16>";
let DiagnosticType = "UImm16_Relaxed";
}
+// FIXME: One of these should probably have UImm16AsmOperandClass as the
+// superclass instead of UImm16RelaxedasmOPerandClass.
def UImm16AsmOperandClass
: UImmAsmOperandClass<16, [UImm16RelaxedAsmOperandClass]>;
def SImm16RelaxedAsmOperandClass
@@ -864,6 +889,10 @@ def simm16_64 : Operand<i64> {
let ParserMatchClass = !cast<AsmOperandClass>("SImm16AsmOperandClass");
}
+// like simm32 but coerces simm32 to uimm32.
+def uimm32_coerced : Operand<i32> {
+ let ParserMatchClass = !cast<AsmOperandClass>("UImm32CoercedAsmOperandClass");
+}
// Like simm32 but coerces uimm32 to simm32.
def simm32_relaxed : Operand<i32> {
let DecoderMethod = "DecodeSImmWithOffsetAndScale<32>";
@@ -2379,11 +2408,12 @@ def : MipsInstAlias<"sync",
// Assembler Pseudo Instructions
//===----------------------------------------------------------------------===//
-// We use i32imm on li/la to defer range checking to the assembler.
+// We use uimm32_coerced to accept a 33 bit signed number that is rendered into
+// a 32 bit number.
class LoadImmediate32<string instr_asm, Operand Od, RegisterOperand RO> :
MipsAsmPseudoInst<(outs RO:$rt), (ins Od:$imm32),
!strconcat(instr_asm, "\t$rt, $imm32")> ;
-def LoadImm32 : LoadImmediate32<"li", i32imm, GPR32Opnd>;
+def LoadImm32 : LoadImmediate32<"li", uimm32_coerced, GPR32Opnd>;
class LoadAddressFromReg32<string instr_asm, Operand MemOpnd,
RegisterOperand RO> :
diff --git a/llvm/lib/Target/Mips/MipsSchedule.td b/llvm/lib/Target/Mips/MipsSchedule.td
index 76bd818a4f1..c0de59ba15f 100644
--- a/llvm/lib/Target/Mips/MipsSchedule.td
+++ b/llvm/lib/Target/Mips/MipsSchedule.td
@@ -270,11 +270,15 @@ def II_ORI : InstrItinClass;
def II_POP : InstrItinClass;
def II_RDHWR : InstrItinClass;
def II_RESTORE : InstrItinClass;
+def II_RECIP_S : InstrItinClass;
+def II_RECIP_D : InstrItinClass;
def II_RINT_S : InstrItinClass;
def II_RINT_D : InstrItinClass;
def II_ROTR : InstrItinClass;
def II_ROTRV : InstrItinClass;
def II_ROUND : InstrItinClass;
+def II_RSQRT_S : InstrItinClass;
+def II_RSQRT_D : InstrItinClass;
def II_SAVE : InstrItinClass;
def II_SC : InstrItinClass;
def II_SCD : InstrItinClass;
@@ -607,6 +611,10 @@ def MipsGenericItineraries : ProcessorItineraries<[ALU, IMULDIV], [], [
InstrItinData<II_NMSUB_D , [InstrStage<8, [ALU]>]>,
InstrItinData<II_DIV_S , [InstrStage<23, [ALU]>]>,
InstrItinData<II_DIV_D , [InstrStage<36, [ALU]>]>,
+ InstrItinData<II_RECIP_D , [InstrStage<25, [ALU]>]>,
+ InstrItinData<II_RECIP_S , [InstrStage<13, [ALU]>]>,
+ InstrItinData<II_RSQRT_D , [InstrStage<29, [ALU]>]>,
+ InstrItinData<II_RSQRT_S , [InstrStage<14, [ALU]>]>,
InstrItinData<II_RINT_D , [InstrStage<1, [ALU]>]>,
InstrItinData<II_RINT_S , [InstrStage<1, [ALU]>]>,
InstrItinData<II_SQRT_S , [InstrStage<54, [ALU]>]>,
diff --git a/llvm/lib/Target/Mips/MipsScheduleGeneric.td b/llvm/lib/Target/Mips/MipsScheduleGeneric.td
index 9712addff1a..15a0401b781 100644
--- a/llvm/lib/Target/Mips/MipsScheduleGeneric.td
+++ b/llvm/lib/Target/Mips/MipsScheduleGeneric.td
@@ -440,6 +440,10 @@ def : ItinRW<[GenericWriteFPUDivD], [II_DIV_D]>;
def : ItinRW<[GenericWriteFPUSqrtS], [II_SQRT_S]>;
def : ItinRW<[GenericWriteFPUSqrtD], [II_SQRT_D]>;
+// rsqrt.[ds], recip.[ds]
+def : ItinRW<[GenericWriteFPURcpS], [II_RECIP_S, II_RSQRT_S]>;
+def : ItinRW<[GenericWriteFPURcpD], [II_RECIP_D, II_RSQRT_D]>;
+
// MIPSR6
// ======
//
diff --git a/llvm/lib/Target/Mips/MipsScheduleP5600.td b/llvm/lib/Target/Mips/MipsScheduleP5600.td
index 976e9f56aff..882a241d142 100644
--- a/llvm/lib/Target/Mips/MipsScheduleP5600.td
+++ b/llvm/lib/Target/Mips/MipsScheduleP5600.td
@@ -448,6 +448,9 @@ def : ItinRW<[P5600WriteFPUSqrtD], [II_SQRT_D]>;
def : InstRW<[P5600WriteFPURsqrtD], (instregex "^FRCP_(W|D)$")>;
def : InstRW<[P5600WriteFPURsqrtD], (instregex "^FRSQRT_(W|D)$")>;
+def : ItinRW<[P5600WriteFPURsqrtD], [II_RECIP_D, II_RSQRT_D]>;
+def : ItinRW<[P5600WriteFPURsqrtS], [II_RECIP_S, II_RSQRT_S]>;
+
// fmadd.[wd], fmsubb.[wd], fdiv.[wd], fsqrt.[wd], fmul.[wd], fadd.[wd],
// fsub.[wd]
def : InstRW<[P5600WriteFPUL_MADDSUB], (instregex "^FMADD_(W|D)$")>;
OpenPOWER on IntegriCloud