summaryrefslogtreecommitdiff
path: root/gcc/config/i386/i386.c
diff options
context:
space:
mode:
authorJohn Carr <jfc@gcc.gnu.org>1998-09-06 05:52:08 +0000
committerJohn Carr <jfc@gcc.gnu.org>1998-09-06 05:52:08 +0000
commita269a03c80a4920f09cf0c065a636f6cedf92490 (patch)
treec62f6e2a1d92a133be181e52cf0f6be0b8b402b4 /gcc/config/i386/i386.c
parentf429f2c549af467352419e0468efe172f014c289 (diff)
downloadgcc-a269a03c80a4920f09cf0c065a636f6cedf92490.tar.gz
final.c (final): If a label is reached only from a single jump...
( * final.c (final): If a label is reached only from a single jump, call NOTICE_UPDATE_CC on the jump and its predecessor before emitting the insn after the label. * i386.h: Add AMD K6 support. Change TARGET_* macros to use table lookup. (INITIALIZE_TRAMPOLINE): Improve trampoline code. (ADJUST_COST): Change definition to call function in i386.c. (ISSUE_RATE): Define as 2 for anything newer than an 80486. * i386.c: Add AMD K6 support. Add constants for feature tests used by TARGET_* macros. (split_di): If before reload, call gen_lowpart and gen_highpart. (x86_adjust_cost): New function. (put_jump_code): New function. (print_operand): New codes 'D' and 'd'. * i386.md: New insn types. New insn attribute "memory". Redefine scheduling parameters to use new types and add AMD K6 support. Explicitly set type of most insns. (move insns): K6 prefers movl $0,reg to xorl reg,reg. Pentium Pro and K6 prefer movl $1,reg to incl reg. (adddi3, subdi3): Set cc_status. (DImode shift patterns): Change label counters from HOST_WIDE_INT to int; x86 can't have more than 2^31 DImode shifts per file. (setcc): Combine all setcc patterns. Allow writing memory. Combine all jump patterns using match_operator. (*bzero): Name pattern. Emit mutliple stos instructions when that is faster than rep stos. (xordi3, anddi3, iordi3): Simplify DImode logical patterns and add define_split. * ch/Make-lang.in: Comment ^L characters. Sun make doesn't like them. From-SVN: r22292
Diffstat (limited to 'gcc/config/i386/i386.c')
-rw-r--r--gcc/config/i386/i386.c230
1 files changed, 224 insertions, 6 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 9354e7920f7..fc8edbd64d1 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -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)
}
}
+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;
+}