diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc
index 647095b6c81..d4251aca80e 100644
--- a/gcc/config/mips/mips.cc
+++ b/gcc/config/mips/mips.cc
@@ -4170,6 +4170,58 @@ mips_set_reg_reg_cost (machine_mode mode)
     }
 }
 
+/* Implement TARGET_INSN_COSTS.  */
+
+static int
+mips_insn_cost (rtx_insn *x, bool speed)
+{
+  int cost;
+  int count;
+  int attr_count;
+  int ratio;
+
+  rtx set = single_set (x);
+  if (!set
+      || (recog_memoized (x) < 0
+	   && GET_CODE (PATTERN (x)) != ASM_INPUT
+	   && asm_noperands (PATTERN (x)) < 0))
+    {
+      if (set)
+	cost = set_rtx_cost (set, speed);
+      else
+	cost = pattern_cost (PATTERN (x), speed);
+      /* If the cost is zero, then it's likely a complex insn.
+	 We don't want the cost of these to be less than
+	 something we know about.  */
+      return cost ? cost : COSTS_N_INSNS (2);
+    }
+
+  if (!speed)
+    return get_attr_length (x);
+
+  cost = rtx_cost_and_count (SET_SRC (set), GET_MODE (SET_DEST (set)),
+		  SET, 1, true, &count);
+  cost = cost ? cost : COSTS_N_INSNS (2);
+  count = count ? count : cost / COSTS_N_INSNS (1);
+  attr_count = get_attr_insn_count (x);
+  ratio = get_attr_perf_ratio (x);
+
+  /* The estimating of rtx_cost_and_count seems good.
+     If we have ratio, we trust it more.  If we don't have ratio,
+     we trust rtx_cost more: so x2.  */
+  if (ratio == 0 && count < attr_count * 2)
+    return cost;
+
+  /* Over estimate the count of instructions.  It normally means that
+     we can combine some INSNs, but rtx_cost have no idea about it.  */
+  if (ratio > 0)
+    return get_attr_insn_count (x) * COSTS_N_INSNS (1) * ratio;
+  else if (cost > count && count > 0)
+    return get_attr_insn_count (x) * cost / count;
+  else
+    return get_attr_insn_count (x) * COSTS_N_INSNS (1);
+}
+
 /* Implement TARGET_RTX_COSTS.  */
 
 static bool
@@ -4195,6 +4247,7 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
     {
       gcc_assert (CONSTANT_P (x));
       *total = 0;
+      *count = 0;
       return true;
     }
 
@@ -4214,6 +4267,7 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
 	  && UINTVAL (x) == 0xffffffff)
 	{
 	  *total = 0;
+	  *count = 0;
 	  return true;
 	}
 
@@ -4223,6 +4277,7 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
 	  if (cost >= 0)
 	    {
 	      *total = cost;
+	      *count = cost / COSTS_N_INSNS (1);
 	      return true;
 	    }
 	}
@@ -4236,6 +4291,7 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
 	  if (speed || mips_immediate_operand_p (outer_code, INTVAL (x)))
 	    {
 	      *total = 0;
+	      *count = 0;
 	      return true;
 	    }
 	}
@@ -4248,6 +4304,7 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
       if (force_to_mem_operand (x, VOIDmode))
 	{
 	  *total = COSTS_N_INSNS (1);
+	  *count = 1;
 	  return true;
 	}
       cost = mips_const_insns (x);
@@ -4281,10 +4338,12 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
 		   && (outer_code == SET || GET_MODE (x) == VOIDmode))
 	    cost = 1;
 	  *total = COSTS_N_INSNS (cost);
+	  *count = cost;
 	  return true;
 	}
       /* The value will need to be fetched from the constant pool.  */
       *total = CONSTANT_POOL_COST;
+      *count = CONSTANT_POOL_COST / COSTS_N_INSNS (1);
       return true;
 
     case MEM:
@@ -4295,6 +4354,7 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
       if (cost > 0)
 	{
 	  *total = COSTS_N_INSNS (cost + 1);
+	  *count = cost;
 	  return true;
 	}
       /* Check for a scaled indexed address.  */
@@ -4302,6 +4362,7 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
 	  || mips_lx_address_p (addr, mode))
 	{
 	  *total = COSTS_N_INSNS (2);
+	  *count = 1;
 	  return true;
 	}
       /* Otherwise use the default handling.  */
@@ -4309,10 +4370,12 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
 
     case FFS:
       *total = COSTS_N_INSNS (6);
+      *count = 1;
       return false;
 
     case NOT:
-      *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 2 : 1);
+      *count = (GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 2 : 1);
+      *total = COSTS_N_INSNS (*count);
       return false;
 
     case AND:
@@ -4325,6 +4388,7 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
 	{
 	  *total = (mips_zero_extend_cost (mode, XEXP (x, 0))
 		    + set_src_cost (XEXP (x, 0), mode, speed));
+	  *count = *total / COSTS_N_INSNS (1);
 	  return true;
 	}
       if (ISA_HAS_CINS && CONST_INT_P (XEXP (x, 1)))
@@ -4336,6 +4400,7 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
 	    {
 	      *total = COSTS_N_INSNS (1);
 	      *total += set_src_cost (XEXP (op, 0), mode, speed);
+	      *count = *total / COSTS_N_INSNS (1);
 	      return true;
 	    }
 	}
@@ -4349,6 +4414,7 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
           *total = (COSTS_N_INSNS (cost)
 		    + set_src_cost (XEXP (XEXP (x, 0), 0), mode, speed)
 		    + set_src_cost (XEXP (XEXP (x, 1), 0), mode, speed));
+	  *count = *total / COSTS_N_INSNS (1);
 	  return true;
 	}
 	    
@@ -4359,6 +4425,7 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
       /* Double-word operations use two single-word operations.  */
       *total = mips_binary_cost (x, COSTS_N_INSNS (1), COSTS_N_INSNS (2),
 				 speed);
+      *count = *total / COSTS_N_INSNS (1);
       return true;
 
     case ASHIFT:
@@ -4372,6 +4439,7 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
       else
 	*total = mips_binary_cost (x, COSTS_N_INSNS (1), COSTS_N_INSNS (12),
 				   speed);
+      *count = *total / COSTS_N_INSNS (1);
       return true;
 
     case ABS:
@@ -4379,12 +4447,14 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
         *total = mips_cost->fp_add;
       else
         *total = COSTS_N_INSNS (4);
+      *count = 1;
       return false;
 
     case LO_SUM:
       /* Low-part immediates need an extended MIPS16 instruction.  */
       *total = (COSTS_N_INSNS (TARGET_MIPS16 ? 2 : 1)
 		+ set_src_cost (XEXP (x, 0), mode, speed));
+      *count = *total / COSTS_N_INSNS (1);
       return true;
 
     case LT:
@@ -4409,10 +4479,12 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
       if (FLOAT_MODE_P (mode))
 	{
 	  *total = mips_cost->fp_add;
+	  *count = 1;
 	  return false;
 	}
       *total = mips_binary_cost (x, COSTS_N_INSNS (1), COSTS_N_INSNS (4),
 				 speed);
+      *count = *total / COSTS_N_INSNS (1);
       return true;
 
     case MINUS:
@@ -4429,6 +4501,7 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
 			+ set_src_cost (XEXP (XEXP (op0, 0), 0), mode, speed)
 			+ set_src_cost (XEXP (op0, 1), mode, speed)
 			+ set_src_cost (op1, mode, speed));
+	      *count = 2;
 	      return true;
 	    }
 	  if (GET_CODE (op1) == MULT)
@@ -4437,6 +4510,7 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
 			+ set_src_cost (op0, mode, speed)
 			+ set_src_cost (XEXP (op1, 0), mode, speed)
 			+ set_src_cost (XEXP (op1, 1), mode, speed));
+	      *count = 2;
 	      return true;
 	    }
 	}
@@ -4448,9 +4522,15 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
 	  /* If this is part of a MADD or MSUB, treat the PLUS as
 	     being free.  */
 	  if (ISA_HAS_UNFUSED_MADD4 && GET_CODE (XEXP (x, 0)) == MULT)
-	    *total = 0;
+	    {
+	      *total = 0;
+	      *count = 0;
+	    }
 	  else
-	    *total = mips_cost->fp_add;
+	    {
+	      *total = mips_cost->fp_add;
+	      *count = 1;
+	    }
 	  return false;
 	}
 
@@ -4466,6 +4546,7 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
 	      *total = (COSTS_N_INSNS (1)
 			+ set_src_cost (XEXP (XEXP (x, 0), 0), mode, speed)
 			+ set_src_cost (XEXP (x, 1), mode, speed));
+	      *count = *total / COSTS_N_INSNS (1);
 	      return true;
 	    }
 	}
@@ -4476,6 +4557,7 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
       *total = mips_binary_cost (x, COSTS_N_INSNS (1),
 				 COSTS_N_INSNS (TARGET_MIPS16 ? 5 : 4),
 				 speed);
+      *count = *total / COSTS_N_INSNS (1);
       return true;
 
     case NEG:
@@ -4491,31 +4573,46 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
 			+ set_src_cost (XEXP (XEXP (op, 0), 0), mode, speed)
 			+ set_src_cost (XEXP (XEXP (op, 0), 1), mode, speed)
 			+ set_src_cost (XEXP (op, 1), mode, speed));
+	      *count = 2;
 	      return true;
 	    }
 	}
 
       if (float_mode_p)
-	*total = mips_cost->fp_add;
+	{
+	  *total = mips_cost->fp_add;
+	  *count = 1;
+	}
       else
-	*total = COSTS_N_INSNS (GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 4 : 1);
+	{
+	  *count = (GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 4 : 1);
+	  *total = COSTS_N_INSNS (*count);
+	}
       return false;
 
     case FMA:
       *total = mips_fp_mult_cost (mode);
+      *count = 1;
       return false;
 
     case MULT:
+      *count = 1;
       if (float_mode_p)
 	*total = mips_fp_mult_cost (mode);
       else if (mode == DImode && !TARGET_64BIT)
-	/* Synthesized from 2 mulsi3s, 1 mulsidi3 and two additions,
-	   where the mulsidi3 always includes an MFHI and an MFLO.  */
-	*total = (speed
-		  ? mips_cost->int_mult_si * 3 + 6
-		  : COSTS_N_INSNS (ISA_HAS_MUL3 ? 7 : 9));
+	{
+	  /* Synthesized from 2 mulsi3s, 1 mulsidi3 and two additions,
+	     where the mulsidi3 always includes an MFHI and an MFLO.  */
+	  *total = (speed
+		    ? mips_cost->int_mult_si * 3 + 6
+		    : COSTS_N_INSNS (ISA_HAS_MUL3 ? 7 : 9));
+	  *count = (speed ? 4 : (ISA_HAS_MUL3 ? 2 : 3));
+	}
       else if (!speed)
-	*total = COSTS_N_INSNS ((ISA_HAS_MUL3 || ISA_HAS_R6MUL) ? 1 : 2) + 1;
+	{
+	  *count = ((ISA_HAS_MUL3 || ISA_HAS_R6MUL) ? 1 : 2);
+	  *total = COSTS_N_INSNS (*count) + 1;
+	}
       else if (mode == DImode)
 	*total = mips_cost->int_mult_di;
       else
@@ -4536,6 +4633,7 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
 	  else
 	    *total = (mips_fp_div_cost (mode)
 		      + set_src_cost (XEXP (x, 1), mode, speed));
+	  *count = 2;
 	  return true;
 	}
       /* Fall through.  */
@@ -4545,12 +4643,14 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
       if (float_mode_p)
 	{
 	  *total = mips_fp_div_cost (mode);
+	  *count = 2;
 	  return false;
 	}
       /* Fall through.  */
 
     case UDIV:
     case UMOD:
+      *count = 1;
       if (!speed)
 	{
 	  /* It is our responsibility to make division by a power of 2
@@ -4565,6 +4665,7 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
 	    {
 	      *total = COSTS_N_INSNS (2);
 	      *total += set_src_cost (XEXP (x, 0), mode, speed);
+	      *count = *total / COSTS_N_INSNS (1);
 	      return true;
 	    }
 	  *total = COSTS_N_INSNS (mips_idiv_insns (mode));
@@ -4577,6 +4678,7 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
 
     case SIGN_EXTEND:
       *total = mips_sign_extend_cost (mode, XEXP (x, 0));
+      *count = *total / COSTS_N_INSNS (1);
       return false;
 
     case ZERO_EXTEND:
@@ -4588,9 +4690,11 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
 	  && GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS)
 	{
 	  *total = set_src_cost (XEXP (XEXP (x, 0), 0), VOIDmode, speed);
+	  *count = *total / COSTS_N_INSNS (1);
 	  return true;
 	}
       *total = mips_zero_extend_cost (mode, XEXP (x, 0));
+      *count = *total / COSTS_N_INSNS (1);
       return false;
     case TRUNCATE:
       /* Costings for highpart multiplies.  Matching patterns of the form:
@@ -4635,7 +4739,7 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
 		*total += rtx_cost (XEXP (op, 0), VOIDmode, GET_CODE (op),
 				    0, speed);
 	    }
-
+	  *count = 3;
 	  return true;
 	}
       return false;
@@ -4646,6 +4750,7 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
     case FLOAT_EXTEND:
     case FLOAT_TRUNCATE:
       *total = mips_cost->fp_add;
+      *count = 1;
       return false;
 
     case SET:
@@ -4653,6 +4758,7 @@ mips_rtx_costs (rtx x, machine_mode mode, int outer_code,
 	  && reg_or_0_operand (SET_SRC (x), VOIDmode))
 	{
 	  *total = mips_set_reg_reg_cost (GET_MODE (SET_DEST (x)));
+	  *count = *total / COSTS_N_INSNS (1);
 	  return true;
 	}
       return false;
@@ -23072,6 +23178,8 @@ mips_bit_clear_p (enum machine_mode mode, unsigned HOST_WIDE_INT m)
 #define TARGET_RTX_COSTS mips_rtx_costs
 #undef TARGET_ADDRESS_COST
 #define TARGET_ADDRESS_COST mips_address_cost
+#undef  TARGET_INSN_COST
+#define TARGET_INSN_COST mips_insn_cost
 
 #undef TARGET_NO_SPECULATION_IN_DELAY_SLOTS_P
 #define TARGET_NO_SPECULATION_IN_DELAY_SLOTS_P mips_no_speculation_in_delay_slots_p
