aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/backend/mips64/instruction-scheduler-mips64.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler/backend/mips64/instruction-scheduler-mips64.cc')
-rw-r--r--deps/v8/src/compiler/backend/mips64/instruction-scheduler-mips64.cc1723
1 files changed, 1723 insertions, 0 deletions
diff --git a/deps/v8/src/compiler/backend/mips64/instruction-scheduler-mips64.cc b/deps/v8/src/compiler/backend/mips64/instruction-scheduler-mips64.cc
new file mode 100644
index 0000000000..a3031cf698
--- /dev/null
+++ b/deps/v8/src/compiler/backend/mips64/instruction-scheduler-mips64.cc
@@ -0,0 +1,1723 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/compiler/backend/instruction-scheduler.h"
+#include "src/macro-assembler.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+bool InstructionScheduler::SchedulerSupported() { return true; }
+
+int InstructionScheduler::GetTargetInstructionFlags(
+ const Instruction* instr) const {
+ switch (instr->arch_opcode()) {
+ case kMips64AbsD:
+ case kMips64AbsS:
+ case kMips64Add:
+ case kMips64AddD:
+ case kMips64AddS:
+ case kMips64And:
+ case kMips64And32:
+ case kMips64AssertEqual:
+ case kMips64BitcastDL:
+ case kMips64BitcastLD:
+ case kMips64ByteSwap32:
+ case kMips64ByteSwap64:
+ case kMips64CeilWD:
+ case kMips64CeilWS:
+ case kMips64Clz:
+ case kMips64Cmp:
+ case kMips64CmpD:
+ case kMips64CmpS:
+ case kMips64Ctz:
+ case kMips64CvtDL:
+ case kMips64CvtDS:
+ case kMips64CvtDUl:
+ case kMips64CvtDUw:
+ case kMips64CvtDW:
+ case kMips64CvtSD:
+ case kMips64CvtSL:
+ case kMips64CvtSUl:
+ case kMips64CvtSUw:
+ case kMips64CvtSW:
+ case kMips64DMulHigh:
+ case kMips64MulHighU:
+ case kMips64Dadd:
+ case kMips64DaddOvf:
+ case kMips64Dclz:
+ case kMips64Dctz:
+ case kMips64Ddiv:
+ case kMips64DdivU:
+ case kMips64Dext:
+ case kMips64Dins:
+ case kMips64Div:
+ case kMips64DivD:
+ case kMips64DivS:
+ case kMips64DivU:
+ case kMips64Dlsa:
+ case kMips64Dmod:
+ case kMips64DmodU:
+ case kMips64Dmul:
+ case kMips64Dpopcnt:
+ case kMips64Dror:
+ case kMips64Dsar:
+ case kMips64Dshl:
+ case kMips64Dshr:
+ case kMips64Dsub:
+ case kMips64DsubOvf:
+ case kMips64Ext:
+ case kMips64F32x4Abs:
+ case kMips64F32x4Add:
+ case kMips64F32x4AddHoriz:
+ case kMips64F32x4Eq:
+ case kMips64F32x4ExtractLane:
+ case kMips64F32x4Lt:
+ case kMips64F32x4Le:
+ case kMips64F32x4Max:
+ case kMips64F32x4Min:
+ case kMips64F32x4Mul:
+ case kMips64F32x4Ne:
+ case kMips64F32x4Neg:
+ case kMips64F32x4RecipApprox:
+ case kMips64F32x4RecipSqrtApprox:
+ case kMips64F32x4ReplaceLane:
+ case kMips64F32x4SConvertI32x4:
+ case kMips64F32x4Splat:
+ case kMips64F32x4Sub:
+ case kMips64F32x4UConvertI32x4:
+ case kMips64Float32Max:
+ case kMips64Float32Min:
+ case kMips64Float32RoundDown:
+ case kMips64Float32RoundTiesEven:
+ case kMips64Float32RoundTruncate:
+ case kMips64Float32RoundUp:
+ case kMips64Float64ExtractLowWord32:
+ case kMips64Float64ExtractHighWord32:
+ case kMips64Float64InsertLowWord32:
+ case kMips64Float64InsertHighWord32:
+ case kMips64Float64Max:
+ case kMips64Float64Min:
+ case kMips64Float64RoundDown:
+ case kMips64Float64RoundTiesEven:
+ case kMips64Float64RoundTruncate:
+ case kMips64Float64RoundUp:
+ case kMips64Float64SilenceNaN:
+ case kMips64FloorWD:
+ case kMips64FloorWS:
+ case kMips64I16x8Add:
+ case kMips64I16x8AddHoriz:
+ case kMips64I16x8AddSaturateS:
+ case kMips64I16x8AddSaturateU:
+ case kMips64I16x8Eq:
+ case kMips64I16x8ExtractLane:
+ case kMips64I16x8GeS:
+ case kMips64I16x8GeU:
+ case kMips64I16x8GtS:
+ case kMips64I16x8GtU:
+ case kMips64I16x8MaxS:
+ case kMips64I16x8MaxU:
+ case kMips64I16x8MinS:
+ case kMips64I16x8MinU:
+ case kMips64I16x8Mul:
+ case kMips64I16x8Ne:
+ case kMips64I16x8Neg:
+ case kMips64I16x8ReplaceLane:
+ case kMips64I8x16SConvertI16x8:
+ case kMips64I16x8SConvertI32x4:
+ case kMips64I16x8SConvertI8x16High:
+ case kMips64I16x8SConvertI8x16Low:
+ case kMips64I16x8Shl:
+ case kMips64I16x8ShrS:
+ case kMips64I16x8ShrU:
+ case kMips64I16x8Splat:
+ case kMips64I16x8Sub:
+ case kMips64I16x8SubSaturateS:
+ case kMips64I16x8SubSaturateU:
+ case kMips64I8x16UConvertI16x8:
+ case kMips64I16x8UConvertI32x4:
+ case kMips64I16x8UConvertI8x16High:
+ case kMips64I16x8UConvertI8x16Low:
+ case kMips64I32x4Add:
+ case kMips64I32x4AddHoriz:
+ case kMips64I32x4Eq:
+ case kMips64I32x4ExtractLane:
+ case kMips64I32x4GeS:
+ case kMips64I32x4GeU:
+ case kMips64I32x4GtS:
+ case kMips64I32x4GtU:
+ case kMips64I32x4MaxS:
+ case kMips64I32x4MaxU:
+ case kMips64I32x4MinS:
+ case kMips64I32x4MinU:
+ case kMips64I32x4Mul:
+ case kMips64I32x4Ne:
+ case kMips64I32x4Neg:
+ case kMips64I32x4ReplaceLane:
+ case kMips64I32x4SConvertF32x4:
+ case kMips64I32x4SConvertI16x8High:
+ case kMips64I32x4SConvertI16x8Low:
+ case kMips64I32x4Shl:
+ case kMips64I32x4ShrS:
+ case kMips64I32x4ShrU:
+ case kMips64I32x4Splat:
+ case kMips64I32x4Sub:
+ case kMips64I32x4UConvertF32x4:
+ case kMips64I32x4UConvertI16x8High:
+ case kMips64I32x4UConvertI16x8Low:
+ case kMips64I8x16Add:
+ case kMips64I8x16AddSaturateS:
+ case kMips64I8x16AddSaturateU:
+ case kMips64I8x16Eq:
+ case kMips64I8x16ExtractLane:
+ case kMips64I8x16GeS:
+ case kMips64I8x16GeU:
+ case kMips64I8x16GtS:
+ case kMips64I8x16GtU:
+ case kMips64I8x16MaxS:
+ case kMips64I8x16MaxU:
+ case kMips64I8x16MinS:
+ case kMips64I8x16MinU:
+ case kMips64I8x16Mul:
+ case kMips64I8x16Ne:
+ case kMips64I8x16Neg:
+ case kMips64I8x16ReplaceLane:
+ case kMips64I8x16Shl:
+ case kMips64I8x16ShrS:
+ case kMips64I8x16ShrU:
+ case kMips64I8x16Splat:
+ case kMips64I8x16Sub:
+ case kMips64I8x16SubSaturateS:
+ case kMips64I8x16SubSaturateU:
+ case kMips64Ins:
+ case kMips64Lsa:
+ case kMips64MaxD:
+ case kMips64MaxS:
+ case kMips64MinD:
+ case kMips64MinS:
+ case kMips64Mod:
+ case kMips64ModU:
+ case kMips64Mov:
+ case kMips64Mul:
+ case kMips64MulD:
+ case kMips64MulHigh:
+ case kMips64MulOvf:
+ case kMips64MulS:
+ case kMips64NegD:
+ case kMips64NegS:
+ case kMips64Nor:
+ case kMips64Nor32:
+ case kMips64Or:
+ case kMips64Or32:
+ case kMips64Popcnt:
+ case kMips64Ror:
+ case kMips64RoundWD:
+ case kMips64RoundWS:
+ case kMips64S128And:
+ case kMips64S128Or:
+ case kMips64S128Not:
+ case kMips64S128Select:
+ case kMips64S128Xor:
+ case kMips64S128Zero:
+ case kMips64S16x8InterleaveEven:
+ case kMips64S16x8InterleaveOdd:
+ case kMips64S16x8InterleaveLeft:
+ case kMips64S16x8InterleaveRight:
+ case kMips64S16x8PackEven:
+ case kMips64S16x8PackOdd:
+ case kMips64S16x2Reverse:
+ case kMips64S16x4Reverse:
+ case kMips64S1x16AllTrue:
+ case kMips64S1x16AnyTrue:
+ case kMips64S1x4AllTrue:
+ case kMips64S1x4AnyTrue:
+ case kMips64S1x8AllTrue:
+ case kMips64S1x8AnyTrue:
+ case kMips64S32x4InterleaveEven:
+ case kMips64S32x4InterleaveOdd:
+ case kMips64S32x4InterleaveLeft:
+ case kMips64S32x4InterleaveRight:
+ case kMips64S32x4PackEven:
+ case kMips64S32x4PackOdd:
+ case kMips64S32x4Shuffle:
+ case kMips64S8x16Concat:
+ case kMips64S8x16InterleaveEven:
+ case kMips64S8x16InterleaveOdd:
+ case kMips64S8x16InterleaveLeft:
+ case kMips64S8x16InterleaveRight:
+ case kMips64S8x16PackEven:
+ case kMips64S8x16PackOdd:
+ case kMips64S8x2Reverse:
+ case kMips64S8x4Reverse:
+ case kMips64S8x8Reverse:
+ case kMips64S8x16Shuffle:
+ case kMips64Sar:
+ case kMips64Seb:
+ case kMips64Seh:
+ case kMips64Shl:
+ case kMips64Shr:
+ case kMips64SqrtD:
+ case kMips64SqrtS:
+ case kMips64Sub:
+ case kMips64SubD:
+ case kMips64SubS:
+ case kMips64TruncLD:
+ case kMips64TruncLS:
+ case kMips64TruncUlD:
+ case kMips64TruncUlS:
+ case kMips64TruncUwD:
+ case kMips64TruncUwS:
+ case kMips64TruncWD:
+ case kMips64TruncWS:
+ case kMips64Tst:
+ case kMips64Xor:
+ case kMips64Xor32:
+ return kNoOpcodeFlags;
+
+ case kMips64Lb:
+ case kMips64Lbu:
+ case kMips64Ld:
+ case kMips64Ldc1:
+ case kMips64Lh:
+ case kMips64Lhu:
+ case kMips64Lw:
+ case kMips64Lwc1:
+ case kMips64Lwu:
+ case kMips64MsaLd:
+ case kMips64Peek:
+ case kMips64Uld:
+ case kMips64Uldc1:
+ case kMips64Ulh:
+ case kMips64Ulhu:
+ case kMips64Ulw:
+ case kMips64Ulwu:
+ case kMips64Ulwc1:
+ case kMips64Word64AtomicLoadUint8:
+ case kMips64Word64AtomicLoadUint16:
+ case kMips64Word64AtomicLoadUint32:
+ case kMips64Word64AtomicLoadUint64:
+
+ return kIsLoadOperation;
+
+ case kMips64ModD:
+ case kMips64ModS:
+ case kMips64MsaSt:
+ case kMips64Push:
+ case kMips64Sb:
+ case kMips64Sd:
+ case kMips64Sdc1:
+ case kMips64Sh:
+ case kMips64StackClaim:
+ case kMips64StoreToStackSlot:
+ case kMips64Sw:
+ case kMips64Swc1:
+ case kMips64Usd:
+ case kMips64Usdc1:
+ case kMips64Ush:
+ case kMips64Usw:
+ case kMips64Uswc1:
+ case kMips64Word64AtomicStoreWord8:
+ case kMips64Word64AtomicStoreWord16:
+ case kMips64Word64AtomicStoreWord32:
+ case kMips64Word64AtomicStoreWord64:
+ case kMips64Word64AtomicAddUint8:
+ case kMips64Word64AtomicAddUint16:
+ case kMips64Word64AtomicAddUint32:
+ case kMips64Word64AtomicAddUint64:
+ case kMips64Word64AtomicSubUint8:
+ case kMips64Word64AtomicSubUint16:
+ case kMips64Word64AtomicSubUint32:
+ case kMips64Word64AtomicSubUint64:
+ case kMips64Word64AtomicAndUint8:
+ case kMips64Word64AtomicAndUint16:
+ case kMips64Word64AtomicAndUint32:
+ case kMips64Word64AtomicAndUint64:
+ case kMips64Word64AtomicOrUint8:
+ case kMips64Word64AtomicOrUint16:
+ case kMips64Word64AtomicOrUint32:
+ case kMips64Word64AtomicOrUint64:
+ case kMips64Word64AtomicXorUint8:
+ case kMips64Word64AtomicXorUint16:
+ case kMips64Word64AtomicXorUint32:
+ case kMips64Word64AtomicXorUint64:
+ case kMips64Word64AtomicExchangeUint8:
+ case kMips64Word64AtomicExchangeUint16:
+ case kMips64Word64AtomicExchangeUint32:
+ case kMips64Word64AtomicExchangeUint64:
+ case kMips64Word64AtomicCompareExchangeUint8:
+ case kMips64Word64AtomicCompareExchangeUint16:
+ case kMips64Word64AtomicCompareExchangeUint32:
+ case kMips64Word64AtomicCompareExchangeUint64:
+ return kHasSideEffect;
+
+#define CASE(Name) case k##Name:
+ COMMON_ARCH_OPCODE_LIST(CASE)
+#undef CASE
+ // Already covered in architecture independent code.
+ UNREACHABLE();
+ }
+
+ UNREACHABLE();
+}
+
+enum Latency {
+ BRANCH = 4, // Estimated max.
+ RINT_S = 4, // Estimated.
+ RINT_D = 4, // Estimated.
+
+ MULT = 4,
+ MULTU = 4,
+ DMULT = 4,
+ DMULTU = 4,
+
+ MUL = 7,
+ DMUL = 7,
+ MUH = 7,
+ MUHU = 7,
+ DMUH = 7,
+ DMUHU = 7,
+
+ DIV = 50, // Min:11 Max:50
+ DDIV = 50,
+ DIVU = 50,
+ DDIVU = 50,
+
+ ABS_S = 4,
+ ABS_D = 4,
+ NEG_S = 4,
+ NEG_D = 4,
+ ADD_S = 4,
+ ADD_D = 4,
+ SUB_S = 4,
+ SUB_D = 4,
+ MAX_S = 4, // Estimated.
+ MIN_S = 4,
+ MAX_D = 4, // Estimated.
+ MIN_D = 4,
+ C_cond_S = 4,
+ C_cond_D = 4,
+ MUL_S = 4,
+
+ MADD_S = 4,
+ MSUB_S = 4,
+ NMADD_S = 4,
+ NMSUB_S = 4,
+
+ CABS_cond_S = 4,
+ CABS_cond_D = 4,
+
+ CVT_D_S = 4,
+ CVT_PS_PW = 4,
+
+ CVT_S_W = 4,
+ CVT_S_L = 4,
+ CVT_D_W = 4,
+ CVT_D_L = 4,
+
+ CVT_S_D = 4,
+
+ CVT_W_S = 4,
+ CVT_W_D = 4,
+ CVT_L_S = 4,
+ CVT_L_D = 4,
+
+ CEIL_W_S = 4,
+ CEIL_W_D = 4,
+ CEIL_L_S = 4,
+ CEIL_L_D = 4,
+
+ FLOOR_W_S = 4,
+ FLOOR_W_D = 4,
+ FLOOR_L_S = 4,
+ FLOOR_L_D = 4,
+
+ ROUND_W_S = 4,
+ ROUND_W_D = 4,
+ ROUND_L_S = 4,
+ ROUND_L_D = 4,
+
+ TRUNC_W_S = 4,
+ TRUNC_W_D = 4,
+ TRUNC_L_S = 4,
+ TRUNC_L_D = 4,
+
+ MOV_S = 4,
+ MOV_D = 4,
+
+ MOVF_S = 4,
+ MOVF_D = 4,
+
+ MOVN_S = 4,
+ MOVN_D = 4,
+
+ MOVT_S = 4,
+ MOVT_D = 4,
+
+ MOVZ_S = 4,
+ MOVZ_D = 4,
+
+ MUL_D = 5,
+ MADD_D = 5,
+ MSUB_D = 5,
+ NMADD_D = 5,
+ NMSUB_D = 5,
+
+ RECIP_S = 13,
+ RECIP_D = 26,
+
+ RSQRT_S = 17,
+ RSQRT_D = 36,
+
+ DIV_S = 17,
+ SQRT_S = 17,
+
+ DIV_D = 32,
+ SQRT_D = 32,
+
+ MTC1 = 4,
+ MTHC1 = 4,
+ DMTC1 = 4,
+ LWC1 = 4,
+ LDC1 = 4,
+
+ MFC1 = 1,
+ MFHC1 = 1,
+ DMFC1 = 1,
+ MFHI = 1,
+ MFLO = 1,
+ SWC1 = 1,
+ SDC1 = 1,
+};
+
+int DadduLatency(bool is_operand_register = true) {
+ if (is_operand_register) {
+ return 1;
+ } else {
+ return 2; // Estimated max.
+ }
+}
+
+int DsubuLatency(bool is_operand_register = true) {
+ return DadduLatency(is_operand_register);
+}
+
+int AndLatency(bool is_operand_register = true) {
+ return DadduLatency(is_operand_register);
+}
+
+int OrLatency(bool is_operand_register = true) {
+ return DadduLatency(is_operand_register);
+}
+
+int NorLatency(bool is_operand_register = true) {
+ if (is_operand_register) {
+ return 1;
+ } else {
+ return 2; // Estimated max.
+ }
+}
+
+int XorLatency(bool is_operand_register = true) {
+ return DadduLatency(is_operand_register);
+}
+
+int MulLatency(bool is_operand_register = true) {
+ if (is_operand_register) {
+ return Latency::MUL;
+ } else {
+ return Latency::MUL + 1;
+ }
+}
+
+int DmulLatency(bool is_operand_register = true) {
+ int latency = 0;
+ if (kArchVariant >= kMips64r6) {
+ latency = Latency::DMUL;
+ } else {
+ latency = Latency::DMULT + Latency::MFLO;
+ }
+ if (!is_operand_register) {
+ latency += 1;
+ }
+ return latency;
+}
+
+int MulhLatency(bool is_operand_register = true) {
+ int latency = 0;
+ if (kArchVariant >= kMips64r6) {
+ latency = Latency::MUH;
+ } else {
+ latency = Latency::MULT + Latency::MFHI;
+ }
+ if (!is_operand_register) {
+ latency += 1;
+ }
+ return latency;
+}
+
+int MulhuLatency(bool is_operand_register = true) {
+ int latency = 0;
+ if (kArchVariant >= kMips64r6) {
+ latency = Latency::MUH;
+ } else {
+ latency = Latency::MULTU + Latency::MFHI;
+ }
+ if (!is_operand_register) {
+ latency += 1;
+ }
+ return latency;
+}
+
+int DMulhLatency(bool is_operand_register = true) {
+ int latency = 0;
+ if (kArchVariant >= kMips64r6) {
+ latency = Latency::DMUH;
+ } else {
+ latency = Latency::DMULT + Latency::MFHI;
+ }
+ if (!is_operand_register) {
+ latency += 1;
+ }
+ return latency;
+}
+
+int DivLatency(bool is_operand_register = true) {
+ if (is_operand_register) {
+ return Latency::DIV;
+ } else {
+ return Latency::DIV + 1;
+ }
+}
+
+int DivuLatency(bool is_operand_register = true) {
+ if (is_operand_register) {
+ return Latency::DIVU;
+ } else {
+ return Latency::DIVU + 1;
+ }
+}
+
+int DdivLatency(bool is_operand_register = true) {
+ int latency = 0;
+ if (kArchVariant >= kMips64r6) {
+ latency = Latency::DDIV;
+ } else {
+ latency = Latency::DDIV + Latency::MFLO;
+ }
+ if (!is_operand_register) {
+ latency += 1;
+ }
+ return latency;
+}
+
+int DdivuLatency(bool is_operand_register = true) {
+ int latency = 0;
+ if (kArchVariant >= kMips64r6) {
+ latency = Latency::DDIVU;
+ } else {
+ latency = Latency::DDIVU + Latency::MFLO;
+ }
+ if (!is_operand_register) {
+ latency += 1;
+ }
+ return latency;
+}
+
+int ModLatency(bool is_operand_register = true) {
+ int latency = 0;
+ if (kArchVariant >= kMips64r6) {
+ latency = 1;
+ } else {
+ latency = Latency::DIV + Latency::MFHI;
+ }
+ if (!is_operand_register) {
+ latency += 1;
+ }
+ return latency;
+}
+
+int ModuLatency(bool is_operand_register = true) {
+ int latency = 0;
+ if (kArchVariant >= kMips64r6) {
+ latency = 1;
+ } else {
+ latency = Latency::DIVU + Latency::MFHI;
+ }
+ if (!is_operand_register) {
+ latency += 1;
+ }
+ return latency;
+}
+
+int DmodLatency(bool is_operand_register = true) {
+ int latency = 0;
+ if (kArchVariant >= kMips64r6) {
+ latency = 1;
+ } else {
+ latency = Latency::DDIV + Latency::MFHI;
+ }
+ if (!is_operand_register) {
+ latency += 1;
+ }
+ return latency;
+}
+
+int DmoduLatency(bool is_operand_register = true) {
+ int latency = 0;
+ if (kArchVariant >= kMips64r6) {
+ latency = 1;
+ } else {
+ latency = Latency::DDIV + Latency::MFHI;
+ }
+ if (!is_operand_register) {
+ latency += 1;
+ }
+ return latency;
+}
+
+int MovzLatency() {
+ if (kArchVariant >= kMips64r6) {
+ return Latency::BRANCH + 1;
+ } else {
+ return 1;
+ }
+}
+
+int MovnLatency() {
+ if (kArchVariant >= kMips64r6) {
+ return Latency::BRANCH + 1;
+ } else {
+ return 1;
+ }
+}
+
+int DlsaLatency() {
+ // Estimated max.
+ return DadduLatency() + 1;
+}
+
+int CallLatency() {
+ // Estimated.
+ return DadduLatency(false) + Latency::BRANCH + 5;
+}
+
+int JumpLatency() {
+ // Estimated max.
+ return 1 + DadduLatency() + Latency::BRANCH + 2;
+}
+
+int SmiUntagLatency() { return 1; }
+
+int PrepareForTailCallLatency() {
+ // Estimated max.
+ return 2 * (DlsaLatency() + DadduLatency(false)) + 2 + Latency::BRANCH +
+ Latency::BRANCH + 2 * DsubuLatency(false) + 2 + Latency::BRANCH + 1;
+}
+
+int AssemblePopArgumentsAdoptFrameLatency() {
+ return 1 + Latency::BRANCH + 1 + SmiUntagLatency() +
+ PrepareForTailCallLatency();
+}
+
+int AssertLatency() { return 1; }
+
+int PrepareCallCFunctionLatency() {
+ int frame_alignment = TurboAssembler::ActivationFrameAlignment();
+ if (frame_alignment > kSystemPointerSize) {
+ return 1 + DsubuLatency(false) + AndLatency(false) + 1;
+ } else {
+ return DsubuLatency(false);
+ }
+}
+
+int AdjustBaseAndOffsetLatency() {
+ return 3; // Estimated max.
+}
+
+int AlignedMemoryLatency() { return AdjustBaseAndOffsetLatency() + 1; }
+
+int UlhuLatency() {
+ if (kArchVariant >= kMips64r6) {
+ return AlignedMemoryLatency();
+ } else {
+ return AdjustBaseAndOffsetLatency() + 2 * AlignedMemoryLatency() + 2;
+ }
+}
+
+int UlwLatency() {
+ if (kArchVariant >= kMips64r6) {
+ return AlignedMemoryLatency();
+ } else {
+ // Estimated max.
+ return AdjustBaseAndOffsetLatency() + 3;
+ }
+}
+
+int UlwuLatency() {
+ if (kArchVariant >= kMips64r6) {
+ return AlignedMemoryLatency();
+ } else {
+ return UlwLatency() + 1;
+ }
+}
+
+int UldLatency() {
+ if (kArchVariant >= kMips64r6) {
+ return AlignedMemoryLatency();
+ } else {
+ // Estimated max.
+ return AdjustBaseAndOffsetLatency() + 3;
+ }
+}
+
+int Ulwc1Latency() {
+ if (kArchVariant >= kMips64r6) {
+ return AlignedMemoryLatency();
+ } else {
+ return UlwLatency() + Latency::MTC1;
+ }
+}
+
+int Uldc1Latency() {
+ if (kArchVariant >= kMips64r6) {
+ return AlignedMemoryLatency();
+ } else {
+ return UldLatency() + Latency::DMTC1;
+ }
+}
+
+int UshLatency() {
+ if (kArchVariant >= kMips64r6) {
+ return AlignedMemoryLatency();
+ } else {
+ // Estimated max.
+ return AdjustBaseAndOffsetLatency() + 2 + 2 * AlignedMemoryLatency();
+ }
+}
+
+int UswLatency() {
+ if (kArchVariant >= kMips64r6) {
+ return AlignedMemoryLatency();
+ } else {
+ return AdjustBaseAndOffsetLatency() + 2;
+ }
+}
+
+int UsdLatency() {
+ if (kArchVariant >= kMips64r6) {
+ return AlignedMemoryLatency();
+ } else {
+ return AdjustBaseAndOffsetLatency() + 2;
+ }
+}
+
+int Uswc1Latency() {
+ if (kArchVariant >= kMips64r6) {
+ return AlignedMemoryLatency();
+ } else {
+ return Latency::MFC1 + UswLatency();
+ }
+}
+
+int Usdc1Latency() {
+ if (kArchVariant >= kMips64r6) {
+ return AlignedMemoryLatency();
+ } else {
+ return Latency::DMFC1 + UsdLatency();
+ }
+}
+
+int Lwc1Latency() { return AdjustBaseAndOffsetLatency() + Latency::LWC1; }
+
+int Swc1Latency() { return AdjustBaseAndOffsetLatency() + Latency::SWC1; }
+
+int Sdc1Latency() { return AdjustBaseAndOffsetLatency() + Latency::SDC1; }
+
+int Ldc1Latency() { return AdjustBaseAndOffsetLatency() + Latency::LDC1; }
+
+int MultiPushLatency() {
+ int latency = DsubuLatency(false);
+ for (int16_t i = kNumRegisters - 1; i >= 0; i--) {
+ latency++;
+ }
+ return latency;
+}
+
+int MultiPushFPULatency() {
+ int latency = DsubuLatency(false);
+ for (int16_t i = kNumRegisters - 1; i >= 0; i--) {
+ latency += Sdc1Latency();
+ }
+ return latency;
+}
+
+int PushCallerSavedLatency(SaveFPRegsMode fp_mode) {
+ int latency = MultiPushLatency();
+ if (fp_mode == kSaveFPRegs) {
+ latency += MultiPushFPULatency();
+ }
+ return latency;
+}
+
+int MultiPopLatency() {
+ int latency = DadduLatency(false);
+ for (int16_t i = 0; i < kNumRegisters; i++) {
+ latency++;
+ }
+ return latency;
+}
+
+int MultiPopFPULatency() {
+ int latency = DadduLatency(false);
+ for (int16_t i = 0; i < kNumRegisters; i++) {
+ latency += Ldc1Latency();
+ }
+ return latency;
+}
+
+int PopCallerSavedLatency(SaveFPRegsMode fp_mode) {
+ int latency = MultiPopLatency();
+ if (fp_mode == kSaveFPRegs) {
+ latency += MultiPopFPULatency();
+ }
+ return latency;
+}
+
+int CallCFunctionHelperLatency() {
+ // Estimated.
+ int latency = AndLatency(false) + Latency::BRANCH + 2 + CallLatency();
+ if (base::OS::ActivationFrameAlignment() > kSystemPointerSize) {
+ latency++;
+ } else {
+ latency += DadduLatency(false);
+ }
+ return latency;
+}
+
+int CallCFunctionLatency() { return 1 + CallCFunctionHelperLatency(); }
+
+int AssembleArchJumpLatency() {
+ // Estimated max.
+ return Latency::BRANCH;
+}
+
+int AssembleArchLookupSwitchLatency(const Instruction* instr) {
+ int latency = 0;
+ for (size_t index = 2; index < instr->InputCount(); index += 2) {
+ latency += 1 + Latency::BRANCH;
+ }
+ return latency + AssembleArchJumpLatency();
+}
+
+int GenerateSwitchTableLatency() {
+ int latency = 0;
+ if (kArchVariant >= kMips64r6) {
+ latency = DlsaLatency() + 2;
+ } else {
+ latency = 6;
+ }
+ latency += 2;
+ return latency;
+}
+
+int AssembleArchTableSwitchLatency() {
+ return Latency::BRANCH + GenerateSwitchTableLatency();
+}
+
+int DropAndRetLatency() {
+ // Estimated max.
+ return DadduLatency(false) + JumpLatency();
+}
+
+int AssemblerReturnLatency() {
+ // Estimated max.
+ return DadduLatency(false) + MultiPopLatency() + MultiPopFPULatency() +
+ Latency::BRANCH + DadduLatency() + 1 + DropAndRetLatency();
+}
+
+int TryInlineTruncateDoubleToILatency() {
+ return 2 + Latency::TRUNC_W_D + Latency::MFC1 + 2 + AndLatency(false) +
+ Latency::BRANCH;
+}
+
+int CallStubDelayedLatency() { return 1 + CallLatency(); }
+
+int TruncateDoubleToIDelayedLatency() {
+ // TODO(mips): This no longer reflects how TruncateDoubleToI is called.
+ return TryInlineTruncateDoubleToILatency() + 1 + DsubuLatency(false) +
+ Sdc1Latency() + CallStubDelayedLatency() + DadduLatency(false) + 1;
+}
+
+int CheckPageFlagLatency() {
+ return AndLatency(false) + AlignedMemoryLatency() + AndLatency(false) +
+ Latency::BRANCH;
+}
+
+int SltuLatency(bool is_operand_register = true) {
+ if (is_operand_register) {
+ return 1;
+ } else {
+ return 2; // Estimated max.
+ }
+}
+
+int BranchShortHelperR6Latency() {
+ return 2; // Estimated max.
+}
+
+int BranchShortHelperLatency() {
+ return SltuLatency() + 2; // Estimated max.
+}
+
+int BranchShortLatency(BranchDelaySlot bdslot = PROTECT) {
+ if (kArchVariant >= kMips64r6 && bdslot == PROTECT) {
+ return BranchShortHelperR6Latency();
+ } else {
+ return BranchShortHelperLatency();
+ }
+}
+
+int MoveLatency() { return 1; }
+
+int MovToFloatParametersLatency() { return 2 * MoveLatency(); }
+
+int MovFromFloatResultLatency() { return MoveLatency(); }
+
+int DaddOverflowLatency() {
+ // Estimated max.
+ return 6;
+}
+
+int DsubOverflowLatency() {
+ // Estimated max.
+ return 6;
+}
+
+int MulOverflowLatency() {
+ // Estimated max.
+ return MulLatency() + MulhLatency() + 2;
+}
+
+int DclzLatency() { return 1; }
+
+int CtzLatency() {
+ if (kArchVariant >= kMips64r6) {
+ return 3 + DclzLatency();
+ } else {
+ return DadduLatency(false) + XorLatency() + AndLatency() + DclzLatency() +
+ 1 + DsubuLatency();
+ }
+}
+
+int DctzLatency() {
+ if (kArchVariant >= kMips64r6) {
+ return 4;
+ } else {
+ return DadduLatency(false) + XorLatency() + AndLatency() + 1 +
+ DsubuLatency();
+ }
+}
+
+int PopcntLatency() {
+ return 2 + AndLatency() + DsubuLatency() + 1 + AndLatency() + 1 +
+ AndLatency() + DadduLatency() + 1 + DadduLatency() + 1 + AndLatency() +
+ 1 + MulLatency() + 1;
+}
+
+int DpopcntLatency() {
+ return 2 + AndLatency() + DsubuLatency() + 1 + AndLatency() + 1 +
+ AndLatency() + DadduLatency() + 1 + DadduLatency() + 1 + AndLatency() +
+ 1 + DmulLatency() + 1;
+}
+
+int CompareFLatency() { return Latency::C_cond_S; }
+
+int CompareF32Latency() { return CompareFLatency(); }
+
+int CompareF64Latency() { return CompareFLatency(); }
+
+int CompareIsNanFLatency() { return CompareFLatency(); }
+
+int CompareIsNanF32Latency() { return CompareIsNanFLatency(); }
+
+int CompareIsNanF64Latency() { return CompareIsNanFLatency(); }
+
+int NegsLatency() {
+ if (kArchVariant >= kMips64r6) {
+ return Latency::NEG_S;
+ } else {
+ // Estimated.
+ return CompareIsNanF32Latency() + 2 * Latency::BRANCH + Latency::NEG_S +
+ Latency::MFC1 + 1 + XorLatency() + Latency::MTC1;
+ }
+}
+
+int NegdLatency() {
+ if (kArchVariant >= kMips64r6) {
+ return Latency::NEG_D;
+ } else {
+ // Estimated.
+ return CompareIsNanF64Latency() + 2 * Latency::BRANCH + Latency::NEG_D +
+ Latency::DMFC1 + 1 + XorLatency() + Latency::DMTC1;
+ }
+}
+
+int Float64RoundLatency() {
+ if (kArchVariant >= kMips64r6) {
+ return Latency::RINT_D + 4;
+ } else {
+ // For ceil_l_d, floor_l_d, round_l_d, trunc_l_d latency is 4.
+ return Latency::DMFC1 + 1 + Latency::BRANCH + Latency::MOV_D + 4 +
+ Latency::DMFC1 + Latency::BRANCH + Latency::CVT_D_L + 2 +
+ Latency::MTHC1;
+ }
+}
+
+int Float32RoundLatency() {
+ if (kArchVariant >= kMips64r6) {
+ return Latency::RINT_S + 4;
+ } else {
+ // For ceil_w_s, floor_w_s, round_w_s, trunc_w_s latency is 4.
+ return Latency::MFC1 + 1 + Latency::BRANCH + Latency::MOV_S + 4 +
+ Latency::MFC1 + Latency::BRANCH + Latency::CVT_S_W + 2 +
+ Latency::MTC1;
+ }
+}
+
+int Float32MaxLatency() {
+ // Estimated max.
+ int latency = CompareIsNanF32Latency() + Latency::BRANCH;
+ if (kArchVariant >= kMips64r6) {
+ return latency + Latency::MAX_S;
+ } else {
+ return latency + 5 * Latency::BRANCH + 2 * CompareF32Latency() +
+ Latency::MFC1 + 1 + Latency::MOV_S;
+ }
+}
+
+int Float64MaxLatency() {
+ // Estimated max.
+ int latency = CompareIsNanF64Latency() + Latency::BRANCH;
+ if (kArchVariant >= kMips64r6) {
+ return latency + Latency::MAX_D;
+ } else {
+ return latency + 5 * Latency::BRANCH + 2 * CompareF64Latency() +
+ Latency::DMFC1 + Latency::MOV_D;
+ }
+}
+
+int Float32MinLatency() {
+ // Estimated max.
+ int latency = CompareIsNanF32Latency() + Latency::BRANCH;
+ if (kArchVariant >= kMips64r6) {
+ return latency + Latency::MIN_S;
+ } else {
+ return latency + 5 * Latency::BRANCH + 2 * CompareF32Latency() +
+ Latency::MFC1 + 1 + Latency::MOV_S;
+ }
+}
+
+int Float64MinLatency() {
+ // Estimated max.
+ int latency = CompareIsNanF64Latency() + Latency::BRANCH;
+ if (kArchVariant >= kMips64r6) {
+ return latency + Latency::MIN_D;
+ } else {
+ return latency + 5 * Latency::BRANCH + 2 * CompareF32Latency() +
+ Latency::DMFC1 + Latency::MOV_D;
+ }
+}
+
+int TruncLSLatency(bool load_status) {
+ int latency = Latency::TRUNC_L_S + Latency::DMFC1;
+ if (load_status) {
+ latency += SltuLatency() + 7;
+ }
+ return latency;
+}
+
+int TruncLDLatency(bool load_status) {
+ int latency = Latency::TRUNC_L_D + Latency::DMFC1;
+ if (load_status) {
+ latency += SltuLatency() + 7;
+ }
+ return latency;
+}
+
+int TruncUlSLatency() {
+ // Estimated max.
+ return 2 * CompareF32Latency() + CompareIsNanF32Latency() +
+ 4 * Latency::BRANCH + Latency::SUB_S + 2 * Latency::TRUNC_L_S +
+ 3 * Latency::DMFC1 + OrLatency() + Latency::MTC1 + Latency::MOV_S +
+ SltuLatency() + 4;
+}
+
+int TruncUlDLatency() {
+ // Estimated max.
+ return 2 * CompareF64Latency() + CompareIsNanF64Latency() +
+ 4 * Latency::BRANCH + Latency::SUB_D + 2 * Latency::TRUNC_L_D +
+ 3 * Latency::DMFC1 + OrLatency() + Latency::DMTC1 + Latency::MOV_D +
+ SltuLatency() + 4;
+}
+
+int PushLatency() { return DadduLatency() + AlignedMemoryLatency(); }
+
+int ByteSwapSignedLatency() { return 2; }
+
+int LlLatency(int offset) {
+ bool is_one_instruction =
+ (kArchVariant == kMips64r6) ? is_int9(offset) : is_int16(offset);
+ if (is_one_instruction) {
+ return 1;
+ } else {
+ return 3;
+ }
+}
+
+int ExtractBitsLatency(bool sign_extend, int size) {
+ int latency = 2;
+ if (sign_extend) {
+ switch (size) {
+ case 8:
+ case 16:
+ case 32:
+ latency += 1;
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ return latency;
+}
+
+int InsertBitsLatency() { return 2 + DsubuLatency(false) + 2; }
+
+int ScLatency(int offset) {
+ bool is_one_instruction =
+ (kArchVariant == kMips64r6) ? is_int9(offset) : is_int16(offset);
+ if (is_one_instruction) {
+ return 1;
+ } else {
+ return 3;
+ }
+}
+
+int Word32AtomicExchangeLatency(bool sign_extend, int size) {
+ return DadduLatency(false) + 1 + DsubuLatency() + 2 + LlLatency(0) +
+ ExtractBitsLatency(sign_extend, size) + InsertBitsLatency() +
+ ScLatency(0) + BranchShortLatency() + 1;
+}
+
+int Word32AtomicCompareExchangeLatency(bool sign_extend, int size) {
+ return 2 + DsubuLatency() + 2 + LlLatency(0) +
+ ExtractBitsLatency(sign_extend, size) + InsertBitsLatency() +
+ ScLatency(0) + BranchShortLatency() + 1;
+}
+
+int InstructionScheduler::GetInstructionLatency(const Instruction* instr) {
+ // Basic latency modeling for MIPS64 instructions. They have been determined
+ // in empirical way.
+ switch (instr->arch_opcode()) {
+ case kArchCallCodeObject:
+ case kArchCallWasmFunction:
+ return CallLatency();
+ case kArchTailCallCodeObjectFromJSFunction:
+ case kArchTailCallCodeObject: {
+ int latency = 0;
+ if (instr->arch_opcode() == kArchTailCallCodeObjectFromJSFunction) {
+ latency = AssemblePopArgumentsAdoptFrameLatency();
+ }
+ return latency + JumpLatency();
+ }
+ case kArchTailCallWasm:
+ case kArchTailCallAddress:
+ return JumpLatency();
+ case kArchCallJSFunction: {
+ int latency = 0;
+ if (FLAG_debug_code) {
+ latency = 1 + AssertLatency();
+ }
+ return latency + 1 + DadduLatency(false) + CallLatency();
+ }
+ case kArchPrepareCallCFunction:
+ return PrepareCallCFunctionLatency();
+ case kArchSaveCallerRegisters: {
+ auto fp_mode =
+ static_cast<SaveFPRegsMode>(MiscField::decode(instr->opcode()));
+ return PushCallerSavedLatency(fp_mode);
+ }
+ case kArchRestoreCallerRegisters: {
+ auto fp_mode =
+ static_cast<SaveFPRegsMode>(MiscField::decode(instr->opcode()));
+ return PopCallerSavedLatency(fp_mode);
+ }
+ case kArchPrepareTailCall:
+ return 2;
+ case kArchCallCFunction:
+ return CallCFunctionLatency();
+ case kArchJmp:
+ return AssembleArchJumpLatency();
+ case kArchLookupSwitch:
+ return AssembleArchLookupSwitchLatency(instr);
+ case kArchTableSwitch:
+ return AssembleArchTableSwitchLatency();
+ case kArchDebugAbort:
+ return CallLatency() + 1;
+ case kArchDebugBreak:
+ return 1;
+ case kArchComment:
+ case kArchNop:
+ case kArchThrowTerminator:
+ case kArchDeoptimize:
+ return 0;
+ case kArchRet:
+ return AssemblerReturnLatency();
+ case kArchStackPointer:
+ case kArchFramePointer:
+ return 1;
+ case kArchParentFramePointer:
+ // Estimated max.
+ return AlignedMemoryLatency();
+ case kArchTruncateDoubleToI:
+ return TruncateDoubleToIDelayedLatency();
+ case kArchStoreWithWriteBarrier:
+ return DadduLatency() + 1 + CheckPageFlagLatency();
+ case kArchStackSlot:
+ // Estimated max.
+ return DadduLatency(false) + AndLatency(false) + AssertLatency() +
+ DadduLatency(false) + AndLatency(false) + BranchShortLatency() +
+ 1 + DsubuLatency() + DadduLatency();
+ case kArchWordPoisonOnSpeculation:
+ return AndLatency();
+ case kIeee754Float64Acos:
+ case kIeee754Float64Acosh:
+ case kIeee754Float64Asin:
+ case kIeee754Float64Asinh:
+ case kIeee754Float64Atan:
+ case kIeee754Float64Atanh:
+ case kIeee754Float64Atan2:
+ case kIeee754Float64Cos:
+ case kIeee754Float64Cosh:
+ case kIeee754Float64Cbrt:
+ case kIeee754Float64Exp:
+ case kIeee754Float64Expm1:
+ case kIeee754Float64Log:
+ case kIeee754Float64Log1p:
+ case kIeee754Float64Log10:
+ case kIeee754Float64Log2:
+ case kIeee754Float64Pow:
+ case kIeee754Float64Sin:
+ case kIeee754Float64Sinh:
+ case kIeee754Float64Tan:
+ case kIeee754Float64Tanh:
+ return PrepareCallCFunctionLatency() + MovToFloatParametersLatency() +
+ CallCFunctionLatency() + MovFromFloatResultLatency();
+ case kMips64Add:
+ case kMips64Dadd:
+ return DadduLatency(instr->InputAt(1)->IsRegister());
+ case kMips64DaddOvf:
+ return DaddOverflowLatency();
+ case kMips64Sub:
+ case kMips64Dsub:
+ return DsubuLatency(instr->InputAt(1)->IsRegister());
+ case kMips64DsubOvf:
+ return DsubOverflowLatency();
+ case kMips64Mul:
+ return MulLatency();
+ case kMips64MulOvf:
+ return MulOverflowLatency();
+ case kMips64MulHigh:
+ return MulhLatency();
+ case kMips64MulHighU:
+ return MulhuLatency();
+ case kMips64DMulHigh:
+ return DMulhLatency();
+ case kMips64Div: {
+ int latency = DivLatency(instr->InputAt(1)->IsRegister());
+ if (kArchVariant >= kMips64r6) {
+ return latency++;
+ } else {
+ return latency + MovzLatency();
+ }
+ }
+ case kMips64DivU: {
+ int latency = DivuLatency(instr->InputAt(1)->IsRegister());
+ if (kArchVariant >= kMips64r6) {
+ return latency++;
+ } else {
+ return latency + MovzLatency();
+ }
+ }
+ case kMips64Mod:
+ return ModLatency();
+ case kMips64ModU:
+ return ModuLatency();
+ case kMips64Dmul:
+ return DmulLatency();
+ case kMips64Ddiv: {
+ int latency = DdivLatency();
+ if (kArchVariant >= kMips64r6) {
+ return latency++;
+ } else {
+ return latency + MovzLatency();
+ }
+ }
+ case kMips64DdivU: {
+ int latency = DdivuLatency();
+ if (kArchVariant >= kMips64r6) {
+ return latency++;
+ } else {
+ return latency + MovzLatency();
+ }
+ }
+ case kMips64Dmod:
+ return DmodLatency();
+ case kMips64DmodU:
+ return DmoduLatency();
+ case kMips64Dlsa:
+ case kMips64Lsa:
+ return DlsaLatency();
+ case kMips64And:
+ return AndLatency(instr->InputAt(1)->IsRegister());
+ case kMips64And32: {
+ bool is_operand_register = instr->InputAt(1)->IsRegister();
+ int latency = AndLatency(is_operand_register);
+ if (is_operand_register) {
+ return latency + 2;
+ } else {
+ return latency + 1;
+ }
+ }
+ case kMips64Or:
+ return OrLatency(instr->InputAt(1)->IsRegister());
+ case kMips64Or32: {
+ bool is_operand_register = instr->InputAt(1)->IsRegister();
+ int latency = OrLatency(is_operand_register);
+ if (is_operand_register) {
+ return latency + 2;
+ } else {
+ return latency + 1;
+ }
+ }
+ case kMips64Nor:
+ return NorLatency(instr->InputAt(1)->IsRegister());
+ case kMips64Nor32: {
+ bool is_operand_register = instr->InputAt(1)->IsRegister();
+ int latency = NorLatency(is_operand_register);
+ if (is_operand_register) {
+ return latency + 2;
+ } else {
+ return latency + 1;
+ }
+ }
+ case kMips64Xor:
+ return XorLatency(instr->InputAt(1)->IsRegister());
+ case kMips64Xor32: {
+ bool is_operand_register = instr->InputAt(1)->IsRegister();
+ int latency = XorLatency(is_operand_register);
+ if (is_operand_register) {
+ return latency + 2;
+ } else {
+ return latency + 1;
+ }
+ }
+ case kMips64Clz:
+ case kMips64Dclz:
+ return DclzLatency();
+ case kMips64Ctz:
+ return CtzLatency();
+ case kMips64Dctz:
+ return DctzLatency();
+ case kMips64Popcnt:
+ return PopcntLatency();
+ case kMips64Dpopcnt:
+ return DpopcntLatency();
+ case kMips64Shl:
+ return 1;
+ case kMips64Shr:
+ case kMips64Sar:
+ return 2;
+ case kMips64Ext:
+ case kMips64Ins:
+ case kMips64Dext:
+ case kMips64Dins:
+ case kMips64Dshl:
+ case kMips64Dshr:
+ case kMips64Dsar:
+ case kMips64Ror:
+ case kMips64Dror:
+ return 1;
+ case kMips64Tst:
+ return AndLatency(instr->InputAt(1)->IsRegister());
+ case kMips64Mov:
+ return 1;
+ case kMips64CmpS:
+ return MoveLatency() + CompareF32Latency();
+ case kMips64AddS:
+ return Latency::ADD_S;
+ case kMips64SubS:
+ return Latency::SUB_S;
+ case kMips64MulS:
+ return Latency::MUL_S;
+ case kMips64DivS:
+ return Latency::DIV_S;
+ case kMips64ModS:
+ return PrepareCallCFunctionLatency() + MovToFloatParametersLatency() +
+ CallCFunctionLatency() + MovFromFloatResultLatency();
+ case kMips64AbsS:
+ return Latency::ABS_S;
+ case kMips64NegS:
+ return NegdLatency();
+ case kMips64SqrtS:
+ return Latency::SQRT_S;
+ case kMips64MaxS:
+ return Latency::MAX_S;
+ case kMips64MinS:
+ return Latency::MIN_S;
+ case kMips64CmpD:
+ return MoveLatency() + CompareF64Latency();
+ case kMips64AddD:
+ return Latency::ADD_D;
+ case kMips64SubD:
+ return Latency::SUB_D;
+ case kMips64MulD:
+ return Latency::MUL_D;
+ case kMips64DivD:
+ return Latency::DIV_D;
+ case kMips64ModD:
+ return PrepareCallCFunctionLatency() + MovToFloatParametersLatency() +
+ CallCFunctionLatency() + MovFromFloatResultLatency();
+ case kMips64AbsD:
+ return Latency::ABS_D;
+ case kMips64NegD:
+ return NegdLatency();
+ case kMips64SqrtD:
+ return Latency::SQRT_D;
+ case kMips64MaxD:
+ return Latency::MAX_D;
+ case kMips64MinD:
+ return Latency::MIN_D;
+ case kMips64Float64RoundDown:
+ case kMips64Float64RoundTruncate:
+ case kMips64Float64RoundUp:
+ case kMips64Float64RoundTiesEven:
+ return Float64RoundLatency();
+ case kMips64Float32RoundDown:
+ case kMips64Float32RoundTruncate:
+ case kMips64Float32RoundUp:
+ case kMips64Float32RoundTiesEven:
+ return Float32RoundLatency();
+ case kMips64Float32Max:
+ return Float32MaxLatency();
+ case kMips64Float64Max:
+ return Float64MaxLatency();
+ case kMips64Float32Min:
+ return Float32MinLatency();
+ case kMips64Float64Min:
+ return Float64MinLatency();
+ case kMips64Float64SilenceNaN:
+ return Latency::SUB_D;
+ case kMips64CvtSD:
+ return Latency::CVT_S_D;
+ case kMips64CvtDS:
+ return Latency::CVT_D_S;
+ case kMips64CvtDW:
+ return Latency::MTC1 + Latency::CVT_D_W;
+ case kMips64CvtSW:
+ return Latency::MTC1 + Latency::CVT_S_W;
+ case kMips64CvtSUw:
+ return 1 + Latency::DMTC1 + Latency::CVT_S_L;
+ case kMips64CvtSL:
+ return Latency::DMTC1 + Latency::CVT_S_L;
+ case kMips64CvtDL:
+ return Latency::DMTC1 + Latency::CVT_D_L;
+ case kMips64CvtDUw:
+ return 1 + Latency::DMTC1 + Latency::CVT_D_L;
+ case kMips64CvtDUl:
+ return 2 * Latency::BRANCH + 3 + 2 * Latency::DMTC1 +
+ 2 * Latency::CVT_D_L + Latency::ADD_D;
+ case kMips64CvtSUl:
+ return 2 * Latency::BRANCH + 3 + 2 * Latency::DMTC1 +
+ 2 * Latency::CVT_S_L + Latency::ADD_S;
+ case kMips64FloorWD:
+ return Latency::FLOOR_W_D + Latency::MFC1;
+ case kMips64CeilWD:
+ return Latency::CEIL_W_D + Latency::MFC1;
+ case kMips64RoundWD:
+ return Latency::ROUND_W_D + Latency::MFC1;
+ case kMips64TruncWD:
+ return Latency::TRUNC_W_D + Latency::MFC1;
+ case kMips64FloorWS:
+ return Latency::FLOOR_W_S + Latency::MFC1;
+ case kMips64CeilWS:
+ return Latency::CEIL_W_S + Latency::MFC1;
+ case kMips64RoundWS:
+ return Latency::ROUND_W_S + Latency::MFC1;
+ case kMips64TruncWS:
+ return Latency::TRUNC_W_S + Latency::MFC1 + 2 + MovnLatency();
+ case kMips64TruncLS:
+ return TruncLSLatency(instr->OutputCount() > 1);
+ case kMips64TruncLD:
+ return TruncLDLatency(instr->OutputCount() > 1);
+ case kMips64TruncUwD:
+ // Estimated max.
+ return CompareF64Latency() + 2 * Latency::BRANCH +
+ 2 * Latency::TRUNC_W_D + Latency::SUB_D + OrLatency() +
+ Latency::MTC1 + Latency::MFC1 + Latency::MTHC1 + 1;
+ case kMips64TruncUwS:
+ // Estimated max.
+ return CompareF32Latency() + 2 * Latency::BRANCH +
+ 2 * Latency::TRUNC_W_S + Latency::SUB_S + OrLatency() +
+ Latency::MTC1 + 2 * Latency::MFC1 + 2 + MovzLatency();
+ case kMips64TruncUlS:
+ return TruncUlSLatency();
+ case kMips64TruncUlD:
+ return TruncUlDLatency();
+ case kMips64BitcastDL:
+ return Latency::DMFC1;
+ case kMips64BitcastLD:
+ return Latency::DMTC1;
+ case kMips64Float64ExtractLowWord32:
+ return Latency::MFC1;
+ case kMips64Float64InsertLowWord32:
+ return Latency::MFHC1 + Latency::MTC1 + Latency::MTHC1;
+ case kMips64Float64ExtractHighWord32:
+ return Latency::MFHC1;
+ case kMips64Float64InsertHighWord32:
+ return Latency::MTHC1;
+ case kMips64Seb:
+ case kMips64Seh:
+ return 1;
+ case kMips64Lbu:
+ case kMips64Lb:
+ case kMips64Lhu:
+ case kMips64Lh:
+ case kMips64Lwu:
+ case kMips64Lw:
+ case kMips64Ld:
+ case kMips64Sb:
+ case kMips64Sh:
+ case kMips64Sw:
+ case kMips64Sd:
+ return AlignedMemoryLatency();
+ case kMips64Lwc1:
+ return Lwc1Latency();
+ case kMips64Ldc1:
+ return Ldc1Latency();
+ case kMips64Swc1:
+ return Swc1Latency();
+ case kMips64Sdc1:
+ return Sdc1Latency();
+ case kMips64Ulhu:
+ case kMips64Ulh:
+ return UlhuLatency();
+ case kMips64Ulwu:
+ return UlwuLatency();
+ case kMips64Ulw:
+ return UlwLatency();
+ case kMips64Uld:
+ return UldLatency();
+ case kMips64Ulwc1:
+ return Ulwc1Latency();
+ case kMips64Uldc1:
+ return Uldc1Latency();
+ case kMips64Ush:
+ return UshLatency();
+ case kMips64Usw:
+ return UswLatency();
+ case kMips64Usd:
+ return UsdLatency();
+ case kMips64Uswc1:
+ return Uswc1Latency();
+ case kMips64Usdc1:
+ return Usdc1Latency();
+ case kMips64Push: {
+ int latency = 0;
+ if (instr->InputAt(0)->IsFPRegister()) {
+ latency = Sdc1Latency() + DsubuLatency(false);
+ } else {
+ latency = PushLatency();
+ }
+ return latency;
+ }
+ case kMips64Peek: {
+ int latency = 0;
+ if (instr->OutputAt(0)->IsFPRegister()) {
+ auto op = LocationOperand::cast(instr->OutputAt(0));
+ switch (op->representation()) {
+ case MachineRepresentation::kFloat64:
+ latency = Ldc1Latency();
+ break;
+ case MachineRepresentation::kFloat32:
+ latency = Latency::LWC1;
+ break;
+ default:
+ UNREACHABLE();
+ }
+ } else {
+ latency = AlignedMemoryLatency();
+ }
+ return latency;
+ }
+ case kMips64StackClaim:
+ return DsubuLatency(false);
+ case kMips64StoreToStackSlot: {
+ int latency = 0;
+ if (instr->InputAt(0)->IsFPRegister()) {
+ if (instr->InputAt(0)->IsSimd128Register()) {
+ latency = 1; // Estimated value.
+ } else {
+ latency = Sdc1Latency();
+ }
+ } else {
+ latency = AlignedMemoryLatency();
+ }
+ return latency;
+ }
+ case kMips64ByteSwap64:
+ return ByteSwapSignedLatency();
+ case kMips64ByteSwap32:
+ return ByteSwapSignedLatency();
+ case kWord32AtomicLoadInt8:
+ case kWord32AtomicLoadUint8:
+ case kWord32AtomicLoadInt16:
+ case kWord32AtomicLoadUint16:
+ case kWord32AtomicLoadWord32:
+ return 2;
+ case kWord32AtomicStoreWord8:
+ case kWord32AtomicStoreWord16:
+ case kWord32AtomicStoreWord32:
+ return 3;
+ case kWord32AtomicExchangeInt8:
+ return Word32AtomicExchangeLatency(true, 8);
+ case kWord32AtomicExchangeUint8:
+ return Word32AtomicExchangeLatency(false, 8);
+ case kWord32AtomicExchangeInt16:
+ return Word32AtomicExchangeLatency(true, 16);
+ case kWord32AtomicExchangeUint16:
+ return Word32AtomicExchangeLatency(false, 16);
+ case kWord32AtomicExchangeWord32:
+ return 2 + LlLatency(0) + 1 + ScLatency(0) + BranchShortLatency() + 1;
+ case kWord32AtomicCompareExchangeInt8:
+ return Word32AtomicCompareExchangeLatency(true, 8);
+ case kWord32AtomicCompareExchangeUint8:
+ return Word32AtomicCompareExchangeLatency(false, 8);
+ case kWord32AtomicCompareExchangeInt16:
+ return Word32AtomicCompareExchangeLatency(true, 16);
+ case kWord32AtomicCompareExchangeUint16:
+ return Word32AtomicCompareExchangeLatency(false, 16);
+ case kWord32AtomicCompareExchangeWord32:
+ return 3 + LlLatency(0) + BranchShortLatency() + 1 + ScLatency(0) +
+ BranchShortLatency() + 1;
+ case kMips64AssertEqual:
+ return AssertLatency();
+ default:
+ return 1;
+ }
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8