Commit a269a03c by John Carr

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
parent f429f2c5
......@@ -34,7 +34,7 @@
# - making any compiler driver (eg: g++)
# - the compiler proper (eg: cc1plus)
# - define the names for selecting the language in LANGUAGES.
#
# define version of GNUCHILL compiler. Note: maybe we have to change the
# mechanism
GNUCHILL_VERSION = 1.5.2
......@@ -62,7 +62,7 @@ CHILL_FLAGS_TO_PASS = \
"CHILL_LIB=$(CHILL_LIB)" \
"CC=$(CC)" \
"GNUCHILL_VERSION=$(GNUCHILL_VERSION)"
#
# Define the names for selecting languages in LANGUAGES.
CHILL: chill cc1chill chill-runtime
......@@ -105,7 +105,7 @@ chill-runtime: stmp-headers $(GCC_PASSES)
cd ch/runtime; $(MAKE) $(FLAGS_TO_PASS) $(CHILL_FLAGS_TO_PASS) GCC_FOR_TARGET="$${thisdir1}/xgcc -B$${thisdir1}/" all ; \
else true; fi ;; \
esac
#
# Build hooks:
CHILL.all.build: chill
......@@ -123,7 +123,7 @@ chill.dvi: $(srcdir)/ch/chill.texi $(srcdir)/extend.texi $(srcdir)/invoke.texi $
TEXINPUTS=${texidir}:$(srcdir):$$TEXINPUTS tex chill.texi
# FIXME: Not sure languages should do this.
cp ch/chill.dvi chill.dvi
#
# Install hooks:
# cc1chill is installed elsewhere as part of $(COMPILERS).
......@@ -166,7 +166,7 @@ CHILL.install-man:
CHILL.uninstall:
-rm -rf $(bindir)/$(CHILL_INSTALL_NAME)
-rm -rf $(bindir)/$(CHILL_CROSS_NAME)
#
# Clean hooks:
# A lot of the ancillary files are deleted by the main makefile.
# We just have to delete files specific to us.
......@@ -183,7 +183,7 @@ CHILL.maintainer-clean:
-rm -f ch/chill.info* ch/chill.dvi ch/chill.??s ch/chill.*aux
# CYGNUS LOCAL: Delete locally created file.
-rm -f ch/hash.h
#
# Stage hooks:
# The main makefile has already created stage?/ch.
......@@ -195,7 +195,7 @@ CHILL.stage3:
-mv ch/*.o stage3/ch
CHILL.stage4:
-mv ch/*.o stage4/ch
#
# Maintenance hooks:
# This target creates the files that can be rebuilt, but go in the
......
......@@ -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;
}
......@@ -155,18 +155,25 @@ extern int target_flags;
#define TARGET_486 (ix86_cpu == PROCESSOR_I486)
#define TARGET_PENTIUM (ix86_cpu == PROCESSOR_PENTIUM)
#define TARGET_PENTIUMPRO (ix86_cpu == PROCESSOR_PENTIUMPRO)
#define TARGET_USE_LEAVE (ix86_cpu == PROCESSOR_I386)
#define TARGET_PUSH_MEMORY (ix86_cpu == PROCESSOR_I386)
#define TARGET_ZERO_EXTEND_WITH_AND (ix86_cpu != PROCESSOR_I386 \
&& ix86_cpu != PROCESSOR_PENTIUMPRO)
#define TARGET_DOUBLE_WITH_ADD (ix86_cpu != PROCESSOR_I386)
#define TARGET_USE_BIT_TEST (ix86_cpu == PROCESSOR_I386)
#define TARGET_UNROLL_STRLEN (ix86_cpu != PROCESSOR_I386)
#define TARGET_USE_Q_REG (ix86_cpu == PROCESSOR_PENTIUM \
|| ix86_cpu == PROCESSOR_PENTIUMPRO)
#define TARGET_USE_ANY_REG (ix86_cpu == PROCESSOR_I486)
#define TARGET_CMOVE (ix86_arch == PROCESSOR_PENTIUMPRO)
#define TARGET_DEEP_BRANCH_PREDICTION (ix86_cpu == PROCESSOR_PENTIUMPRO)
#define TARGET_K6 (ix86_cpu == PROCESSOR_K6)
#define CPUMASK (1 << ix86_cpu)
extern const int x86_use_leave, x86_push_memory, x86_zero_extend_with_and;
extern const int x86_use_bit_test, x86_cmove, x86_deep_branch;
extern const int x86_unroll_strlen, x86_use_q_reg, x86_use_any_reg;
extern const int x86_double_with_add;
#define TARGET_USE_LEAVE (x86_use_leave & CPUMASK)
#define TARGET_PUSH_MEMORY (x86_push_memory & CPUMASK)
#define TARGET_ZERO_EXTEND_WITH_AND (x86_zero_extend_with_and & CPUMASK)
#define TARGET_USE_BIT_TEST (x86_use_bit_test & CPUMASK)
#define TARGET_UNROLL_STRLEN (x86_unroll_strlen & CPUMASK)
#define TARGET_USE_Q_REG (x86_use_q_reg & CPUMASK)
#define TARGET_USE_ANY_REG (x86_use_any_reg & CPUMASK)
#define TARGET_CMOVE (x86_cmove & (1 << ix86_arch))
#define TARGET_DEEP_BRANCH_PREDICTION (x86_deep_branch & CPUMASK)
#define TARGET_DOUBLE_WITH_ADD (x86_double_with_add & CPUMASK)
#define TARGET_STACK_PROBE (target_flags & MASK_STACK_PROBE)
#define TARGET_SWITCHES \
......@@ -219,7 +226,8 @@ enum processor_type
{PROCESSOR_I386, /* 80386 */
PROCESSOR_I486, /* 80486DX, 80486SX, 80486DX[24] */
PROCESSOR_PENTIUM,
PROCESSOR_PENTIUMPRO};
PROCESSOR_PENTIUMPRO,
PROCESSOR_K6};
#define PROCESSOR_I386_STRING "i386"
#define PROCESSOR_I486_STRING "i486"
......@@ -227,28 +235,20 @@ enum processor_type
#define PROCESSOR_PENTIUM_STRING "pentium"
#define PROCESSOR_I686_STRING "i686"
#define PROCESSOR_PENTIUMPRO_STRING "pentiumpro"
#define PROCESSOR_K6_STRING "k6"
extern enum processor_type ix86_cpu;
extern int ix86_arch;
/* Define the default processor. This is overridden by other tm.h files. */
#define PROCESSOR_DEFAULT \
((enum processor_type) TARGET_CPU_DEFAULT == PROCESSOR_I486) \
? PROCESSOR_I486 \
: ((enum processor_type) TARGET_CPU_DEFAULT == PROCESSOR_PENTIUM) \
? PROCESSOR_PENTIUM \
: ((enum processor_type) TARGET_CPU_DEFAULT == PROCESSOR_PENTIUMPRO) \
? PROCESSOR_PENTIUMPRO \
: PROCESSOR_I386
#define PROCESSOR_DEFAULT (enum processor_type) TARGET_CPU_DEFAULT
#define PROCESSOR_DEFAULT_STRING \
((enum processor_type) TARGET_CPU_DEFAULT == PROCESSOR_I486) \
? PROCESSOR_I486_STRING \
: ((enum processor_type) TARGET_CPU_DEFAULT == PROCESSOR_PENTIUM) \
? PROCESSOR_PENTIUM_STRING \
: ((enum processor_type) TARGET_CPU_DEFAULT == PROCESSOR_PENTIUMPRO) \
? PROCESSOR_PENTIUMPRO_STRING \
: PROCESSOR_I386_STRING
(PROCESSOR_DEFAULT == PROCESSOR_I486 ? PROCESSOR_I486_STRING \
: PROCESSOR_DEFAULT == PROCESSOR_PENTIUM ? PROCESSOR_PENTIUM_STRING \
: PROCESSOR_DEFAULT == PROCESSOR_PENTIUMPRO ? PROCESSOR_PENTIUMPRO_STRING \
: PROCESSOR_DEFAULT == PROCESSOR_K6 ? PROCESSOR_K6_STRING \
: PROCESSOR_I386_STRING)
/* This macro is similar to `TARGET_SWITCHES' but defines names of
command options that have values. Its definition is an
......@@ -1533,25 +1533,16 @@ do { \
/* Output assembler code for a block containing the constant parts
of a trampoline, leaving space for the variable parts. */
/* On the 386, the trampoline contains three instructions:
/* On the 386, the trampoline contains two instructions:
mov #STATIC,ecx
mov #FUNCTION,eax
jmp @eax */
#define TRAMPOLINE_TEMPLATE(FILE) \
{ \
ASM_OUTPUT_CHAR (FILE, GEN_INT (0xb9)); \
ASM_OUTPUT_SHORT (FILE, const0_rtx); \
ASM_OUTPUT_SHORT (FILE, const0_rtx); \
ASM_OUTPUT_CHAR (FILE, GEN_INT (0xb8)); \
ASM_OUTPUT_SHORT (FILE, const0_rtx); \
ASM_OUTPUT_SHORT (FILE, const0_rtx); \
ASM_OUTPUT_CHAR (FILE, GEN_INT (0xff)); \
ASM_OUTPUT_CHAR (FILE, GEN_INT (0xe0)); \
}
jmp FUNCTION
The trampoline is generated entirely at runtime. The operand of JMP
is the address of FUNCTION relative to the instruction following the
JMP (which is 5 bytes long). */
/* Length in units of the trampoline for entering a nested function. */
#define TRAMPOLINE_SIZE 12
#define TRAMPOLINE_SIZE 10
/* Emit RTL insns to initialize the variable parts of a trampoline.
FNADDR is an RTX for the address of the function's pure code.
......@@ -1559,8 +1550,14 @@ do { \
#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
{ \
/* Compute offset from the end of the jmp to the target function. */ \
rtx disp = expand_binop (SImode, sub_optab, FNADDR, \
plus_constant (TRAMP, 10), \
NULL_RTX, 1, OPTAB_DIRECT); \
emit_move_insn (gen_rtx_MEM (QImode, TRAMP), GEN_INT (0xb9)); \
emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 1)), CXT); \
emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 6)), FNADDR); \
emit_move_insn (gen_rtx_MEM (QImode, plus_constant (TRAMP, 5)), GEN_INT (0xe9));\
emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 6)), disp); \
}
/* Definitions for register eliminations.
......@@ -2243,70 +2240,7 @@ while (0)
the same cost as a data-dependence. */
#define ADJUST_COST(insn,link,dep_insn,cost) \
{ \
rtx next_inst; \
if (GET_CODE (dep_insn) == CALL_INSN) \
(cost) = 0; \
\
else 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)))) \
{ \
(cost) = 0; \
} \
\
else if (GET_CODE (insn) == JUMP_INSN) \
{ \
(cost) = 0; \
} \
\
if (TARGET_PENTIUM) \
{ \
if (cost !=0 && is_fp_insn (insn) && is_fp_insn (dep_insn) \
&& !is_fp_dest (dep_insn)) \
{ \
(cost) = 0; \
} \
\
if (agi_dependent (insn, dep_insn)) \
{ \
(cost) = 3; \
} \
else 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 */ \
(cost) = 0; \
} \
} \
else \
if (!is_fp_dest (dep_insn)) \
{ \
if(!agi_dependent (insn, dep_insn)) \
(cost) = 0; \
else if (TARGET_486) \
(cost) = 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)) \
{ \
(cost) = 3; \
} \
}
(cost) = x86_adjust_cost(insn, link, dep_insn, cost)
#define ADJUST_BLOCKAGE(last_insn,insn,blockage) \
{ \
......@@ -2323,6 +2257,8 @@ while (0)
} \
}
#define ISSUE_RATE ((int)ix86_cpu > (int)PROCESSOR_I486 ? 2 : 1)
/* Add any extra modes needed to represent the condition code.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment