diff options
author | John Carr <jfc@gcc.gnu.org> | 1998-09-06 05:52:08 +0000 |
---|---|---|
committer | John Carr <jfc@gcc.gnu.org> | 1998-09-06 05:52:08 +0000 |
commit | a269a03c80a4920f09cf0c065a636f6cedf92490 (patch) | |
tree | c62f6e2a1d92a133be181e52cf0f6be0b8b402b4 /gcc/config/i386/i386.c | |
parent | f429f2c549af467352419e0468efe172f014c289 (diff) | |
download | gcc-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.c | 230 |
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; +} |