]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/config/i386/i386.c
final.c (final): If a label is reached only from a single jump...
[gcc.git] / gcc / config / i386 / i386.c
index 9354e7920f7faee45537383619671442f0a3bda7..fc8edbd64d1e85a5199ae431d269e84b9f06d07a 100644 (file)
@@ -100,8 +100,37 @@ struct processor_costs pentiumpro_cost = {
   17                                   /* cost of a divide/mod */
 };
 
+struct processor_costs k6_cost = {
+  1,                                   /* cost of an add instruction */
+  1,                                   /* cost of a lea instruction */
+  1,                                   /* variable shift costs */
+  1,                                   /* constant shift costs */
+  2,                                   /* cost of starting a multiply */
+  0,                                   /* cost of multiply per each bit set */
+  18                                   /* cost of a divide/mod */
+};
+
 struct processor_costs *ix86_cost = &pentium_cost;
 
+/* Processor feature/optimization bitmasks.  */
+#define m_386 (1<<PROCESSOR_I386)
+#define m_486 (1<<PROCESSOR_I486)
+#define m_PENT (1<<PROCESSOR_PENTIUM)
+#define m_PPRO (1<<PROCESSOR_PENTIUMPRO)
+#define m_K6  (1<<PROCESSOR_K6)
+
+const int x86_use_leave = m_386 | m_K6;
+const int x86_push_memory = m_386 | m_K6;
+const int x86_zero_extend_with_and = m_486 | m_PENT;
+const int x86_movx = m_386 | m_PPRO | m_K6;
+const int x86_double_with_add = ~m_386;
+const int x86_use_bit_test = m_386;
+const int x86_unroll_strlen = m_486 | m_PENT | m_PPRO;
+const int x86_use_q_reg = m_PENT | m_PPRO | m_K6;
+const int x86_use_any_reg = m_486;
+const int x86_cmove = m_PPRO;
+const int x86_deep_branch = m_PPRO| m_K6;
+
 #define AT_BP(mode) (gen_rtx_MEM ((mode), frame_pointer_rtx))
 
 extern FILE *asm_out_file;
@@ -213,7 +242,8 @@ override_options ()
           {PROCESSOR_I686_STRING, PROCESSOR_PENTIUMPRO, &pentiumpro_cost,
              0, 0},
           {PROCESSOR_PENTIUMPRO_STRING, PROCESSOR_PENTIUMPRO,
-             &pentiumpro_cost, 0, 0}};
+             &pentiumpro_cost, 0, 0},
+          {PROCESSOR_K6_STRING, PROCESSOR_K6, &k6_cost, 0, 0}};
 
   int ptt_size = sizeof (processor_target_table) / sizeof (struct ptt);
 
@@ -279,7 +309,7 @@ override_options ()
       {
        ix86_cpu = processor_target_table[j].processor;
        ix86_cost = processor_target_table[j].cost;
-       if (i > j && (int) ix86_arch >= (int) PROCESSOR_PENTIUMPRO)
+       if (i > j && (int) ix86_arch >= (int) PROCESSOR_K6)
          error ("-mcpu=%s does not support -march=%s",
                 ix86_cpu_string, ix86_arch_string);
 
@@ -1586,6 +1616,7 @@ standard_80387_constant_p (x)
   /* Note that on the 80387, other constants, such as pi,
      are much slower to load as standard constants
      than to load from doubles in memory!  */
+  /* ??? Not true on K6: all constants are equal cost.  */
 #endif
 
   return 0;
@@ -2933,8 +2964,8 @@ legitimize_address (x, oldx, mode)
       && (log = (unsigned)exact_log2 (INTVAL (XEXP (x, 1)))) < 4)
     {
       changed = 1;
-      x = gen_rtx (MULT, Pmode, force_reg (Pmode, XEXP (x, 0)),
-                  GEN_INT (1 << log));
+      x = gen_rtx_MULT (Pmode, force_reg (Pmode, XEXP (x, 0)),
+                       GEN_INT (1 << log));
     }
 
   if (GET_CODE (x) == PLUS)
@@ -3185,6 +3216,114 @@ output_pic_addr_const (file, x, code)
     }
 }
 \f
+static void
+put_jump_code (code, reverse, file)
+     enum rtx_code code;
+     int reverse;
+     FILE *file;
+{
+  int flags = cc_prev_status.flags;
+  int ieee = (TARGET_IEEE_FP && (flags & CC_IN_80387));
+  const char *suffix;
+
+  if (flags & CC_Z_IN_NOT_C)
+    switch (code)
+      {
+      case EQ:
+       fputs (reverse ? "c" : "nc", file);
+       return;
+
+      case NE:
+       fputs (reverse ? "nc" : "c", file);
+       return;
+
+      default:
+       abort ();
+      }
+  if (ieee)
+    {
+      switch (code)
+       {
+       case LE:
+         suffix = reverse ? "ae" : "b";
+         break;
+       case GT:
+       case LT:
+       case GE:
+         suffix = reverse ? "ne" : "e";
+         break;
+       case EQ:
+         suffix = reverse ? "ne" : "e";
+         break;
+       case NE:
+         suffix = reverse ? "e" : "ne";
+         break;
+       default:
+         abort ();
+       }
+      fputs (suffix, file);
+      return;
+    }
+  if (flags & CC_TEST_AX)
+    abort();
+  if ((flags & CC_NO_OVERFLOW) && (code == LE || code == GT))
+    abort ();
+  if (reverse)
+    code = reverse_condition (code);
+  switch (code)
+    {
+    case EQ:
+      suffix = "e";
+      break;
+
+    case NE:
+      suffix = "ne";
+      break;
+
+    case GT:
+      suffix = flags & CC_IN_80387 ? "a" : "g";
+      break;
+
+    case GTU:
+      suffix = "a";
+      break;
+
+    case LT:
+      if (flags & CC_NO_OVERFLOW)
+       suffix = "s";
+      else
+       suffix = flags & CC_IN_80387 ? "b" : "l";
+      break;
+
+    case LTU:
+      suffix = "b";
+      break;
+
+    case GE:
+      if (flags & CC_NO_OVERFLOW)
+       suffix = "ns";
+      else
+       suffix = flags & CC_IN_80387 ? "ae" : "ge";
+      break;
+
+    case GEU:
+      suffix = "ae";
+      break;
+
+    case LE:
+      suffix = flags & CC_IN_80387 ? "be" : "le";
+      break;
+
+    case LEU:
+      suffix = "be";
+      break;
+
+    default:
+      abort ();
+    }
+  fputs (suffix, file);
+}
+
 /* Append the correct conditional move suffix which corresponds to CODE.  */
 
 static void
@@ -3301,7 +3440,9 @@ put_condition_code (code, reverse_cc, mode, file)
    C -- print opcode suffix for set/cmov insn.
    c -- like C, but print reversed condition
    F -- print opcode suffix for fcmov insn.
-   f -- like C, but print reversed condition
+   f -- like F, but print reversed condition
+   D -- print the opcode suffix for a jump
+   d -- like D, but print reversed condition
    R -- print the prefix for register names.
    z -- print the opcode suffix for the size of the current operand.
    * -- print a star (in certain assembler syntax)
@@ -3443,6 +3584,14 @@ print_operand (file, x, code)
 
          return;
 
+       case 'D':
+         put_jump_code (GET_CODE (x), 0, file);
+         return;
+
+       case 'd':
+         put_jump_code (GET_CODE (x), 1, file);
+         return;
+
          /* This is used by the conditional move instructions.  */
        case 'C':
          put_condition_code (GET_CODE (x), 0, MODE_INT, file);
@@ -3851,7 +4000,12 @@ split_di (operands, num, lo_half, hi_half)
   while (num--)
     {
       rtx op = operands[num];
-      if (GET_CODE (op) == REG)
+      if (! reload_completed)
+       {
+         lo_half[num] = gen_lowpart (SImode, op);
+         hi_half[num] = gen_highpart (SImode, op);
+       }
+      else if (GET_CODE (op) == REG)
        {
          lo_half[num] = gen_rtx_REG (SImode, REGNO (op));
          hi_half[num] = gen_rtx_REG (SImode, REGNO (op) + 1);
@@ -5360,3 +5514,67 @@ output_int_conditional_move (which_alternative, operands)
 
   return "";
 }
+
+int
+x86_adjust_cost (insn, link, dep_insn, cost)
+     rtx insn, link, dep_insn;
+     int cost;
+{
+  rtx next_inst;
+
+  if (GET_CODE (dep_insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN)
+    return 0;
+
+  if (GET_CODE (dep_insn) == INSN
+      && GET_CODE (PATTERN (dep_insn)) == SET
+      && GET_CODE (SET_DEST (PATTERN (dep_insn))) == REG
+      && GET_CODE (insn) == INSN
+      && GET_CODE (PATTERN (insn)) == SET
+      && !reg_overlap_mentioned_p (SET_DEST (PATTERN (dep_insn)),
+                                  SET_SRC (PATTERN (insn))))
+    return 0;  /* ??? */
+
+
+  switch (ix86_cpu)
+    {
+    case PROCESSOR_PENTIUM:
+      if (cost != 0 && is_fp_insn (insn) && is_fp_insn (dep_insn)
+         && !is_fp_dest (dep_insn))
+       return 0;
+
+      if (agi_dependent (insn, dep_insn))
+       return 3;
+
+      if (GET_CODE (insn) == INSN
+         && GET_CODE (PATTERN (insn)) == SET
+         && SET_DEST (PATTERN (insn)) == cc0_rtx
+         && (next_inst = next_nonnote_insn (insn))
+         && GET_CODE (next_inst) == JUMP_INSN)
+       /* compare probably paired with jump */
+       return 0;
+      break;
+
+    case PROCESSOR_K6:
+    default:
+      if (!is_fp_dest (dep_insn))
+       {
+         if(!agi_dependent (insn, dep_insn))
+           return 0;
+         if (TARGET_486)
+           return 2;
+       }
+      else
+       if (is_fp_store (insn) && is_fp_insn (dep_insn)
+           && NEXT_INSN (insn) && NEXT_INSN (NEXT_INSN (insn))
+           && NEXT_INSN (NEXT_INSN (NEXT_INSN (insn)))
+           && (GET_CODE (NEXT_INSN (insn)) == INSN)
+           && (GET_CODE (NEXT_INSN (NEXT_INSN (insn))) == JUMP_INSN)
+           && (GET_CODE (NEXT_INSN (NEXT_INSN (NEXT_INSN (insn)))) == NOTE)
+           && (NOTE_LINE_NUMBER (NEXT_INSN (NEXT_INSN (NEXT_INSN (insn))))
+               == NOTE_INSN_LOOP_END))
+         return 3;
+      break;
+    }
+
+  return cost;
+}
This page took 0.035535 seconds and 5 git commands to generate.