i386.c (split_ti): New function.

* i386.c (split_ti): New function.
	(ix86_split_to_parts): Support TImodes.
	* i386.h (VALID_INT_MODE_P): Add TImode.
	* i386.md (movdi splitter): Fix.
	(movti): Support 64bit integer registers.
	(movti_rex64): New function and splitter.

	* i386.c (*_cost): Add movsx/movzx cost.
	* i386.h (struct processor_costs): Add movsx/movzx fields.
	(RTX_COSTS): Handle zero/sign extend + avoid believing that
	64bit operations require split on 64bit machine.
	(CONST_COST): Make large 64bit constants expensive on 64bit compilation.

	* i386.c (ix86_setup_incomming_varargs): Fix mode of PLUS.
	(ix86_expand_move): Avoid pushes of memory if size does not match;
	move long constants to register.
	(x86_initialize_trampoline): Fix mode.
	* i386.h (ASM_OUTPUT_ADDR_VEC_ELT, ASM_OUTPUT_ADDR_DIFF_ELT):
	Use ASM_QUAD on 64bit.
	* i386.md (test pattern): Disallow impossible constants.
	(tablejump PIC expander): Fix emitting of sum.
	(movdicc_rex64): Rename to movdicc.
	* linux64.h (LINK_SPEC): Add missing '%'.

From-SVN: r46296
This commit is contained in:
Jan Hubicka 2001-10-17 00:04:20 +02:00 committed by Jan Hubicka
parent c0e5eb1602
commit 44cf5b6a71
5 changed files with 179 additions and 18 deletions

View File

@ -1,3 +1,29 @@
Wed Oct 17 00:01:02 CEST 2001 Jan Hubicka <jh@suse.cz>
* i386.c (split_ti): New function.
(ix86_split_to_parts): Support TImodes.
* i386.h (VALID_INT_MODE_P): Add TImode.
* i386.md (movdi splitter): Fix.
(movti): Support 64bit integer registers.
(movti_rex64): New function and splitter.
* i386.c (*_cost): Add movsx/movzx cost.
* i386.h (struct processor_costs): Add movsx/movzx fields.
(RTX_COSTS): Handle zero/sign extend + avoid believing that
64bit operations require split on 64bit machine.
(CONST_COST): Make large 64bit constants expensive on 64bit compilation.
* i386.c (ix86_setup_incomming_varargs): Fix mode of PLUS.
(ix86_expand_move): Avoid pushes of memory if size does not match;
move long constants to register.
(x86_initialize_trampoline): Fix mode.
* i386.h (ASM_OUTPUT_ADDR_VEC_ELT, ASM_OUTPUT_ADDR_DIFF_ELT):
Use ASM_QUAD on 64bit.
* i386.md (test pattern): Disallow impossible constants.
(tablejump PIC expander): Fix emitting of sum.
(movdicc_rex64): Rename to movdicc.
* linux64.h (LINK_SPEC): Add missing '%'.
2001-10-16 Alexandre Oliva <aoliva@redhat.com>
* tree-inline.c (inlinable_function_p): Leave it up to the

View File

@ -57,6 +57,8 @@ struct processor_costs size_cost = { /* costs for tunning for size */
3, /* cost of starting a multiply */
0, /* cost of multiply per each bit set */
3, /* cost of a divide/mod */
3, /* cost of movsx */
3, /* cost of movzx */
0, /* "large" insn */
2, /* MOVE_RATIO */
2, /* cost for loading QImode using movzbl */
@ -90,6 +92,8 @@ struct processor_costs i386_cost = { /* 386 specific costs */
6, /* cost of starting a multiply */
1, /* cost of multiply per each bit set */
23, /* cost of a divide/mod */
3, /* cost of movsx */
2, /* cost of movzx */
15, /* "large" insn */
3, /* MOVE_RATIO */
4, /* cost for loading QImode using movzbl */
@ -123,6 +127,8 @@ struct processor_costs i486_cost = { /* 486 specific costs */
12, /* cost of starting a multiply */
1, /* cost of multiply per each bit set */
40, /* cost of a divide/mod */
3, /* cost of movsx */
2, /* cost of movzx */
15, /* "large" insn */
3, /* MOVE_RATIO */
4, /* cost for loading QImode using movzbl */
@ -156,6 +162,8 @@ struct processor_costs pentium_cost = {
11, /* cost of starting a multiply */
0, /* cost of multiply per each bit set */
25, /* cost of a divide/mod */
3, /* cost of movsx */
2, /* cost of movzx */
8, /* "large" insn */
6, /* MOVE_RATIO */
6, /* cost for loading QImode using movzbl */
@ -189,6 +197,8 @@ struct processor_costs pentiumpro_cost = {
4, /* cost of starting a multiply */
0, /* cost of multiply per each bit set */
17, /* cost of a divide/mod */
1, /* cost of movsx */
1, /* cost of movzx */
8, /* "large" insn */
6, /* MOVE_RATIO */
2, /* cost for loading QImode using movzbl */
@ -222,6 +232,8 @@ struct processor_costs k6_cost = {
3, /* cost of starting a multiply */
0, /* cost of multiply per each bit set */
18, /* cost of a divide/mod */
2, /* cost of movsx */
2, /* cost of movzx */
8, /* "large" insn */
4, /* MOVE_RATIO */
3, /* cost for loading QImode using movzbl */
@ -255,6 +267,8 @@ struct processor_costs athlon_cost = {
5, /* cost of starting a multiply */
0, /* cost of multiply per each bit set */
42, /* cost of a divide/mod */
1, /* cost of movsx */
1, /* cost of movzx */
8, /* "large" insn */
9, /* MOVE_RATIO */
4, /* cost for loading QImode using movzbl */
@ -288,6 +302,8 @@ struct processor_costs pentium4_cost = {
30, /* cost of starting a multiply */
0, /* cost of multiply per each bit set */
112, /* cost of a divide/mod */
1, /* cost of movsx */
1, /* cost of movzx */
16, /* "large" insn */
6, /* MOVE_RATIO */
2, /* cost for loading QImode using movzbl */
@ -2212,7 +2228,7 @@ ix86_setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl)
nsse_reg = gen_reg_rtx (Pmode);
emit_insn (gen_zero_extendqidi2 (nsse_reg, gen_rtx_REG (QImode, 0)));
emit_insn (gen_rtx_SET (VOIDmode, tmp_reg,
gen_rtx_MULT (VOIDmode, nsse_reg,
gen_rtx_MULT (Pmode, nsse_reg,
GEN_INT (4))));
if (next_cum.sse_regno)
emit_move_insn
@ -5938,6 +5954,57 @@ split_di (operands, num, lo_half, hi_half)
abort ();
}
}
/* Split one or more TImode RTL references into pairs of SImode
references. The RTL can be REG, offsettable MEM, integer constant, or
CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
split and "num" is its length. lo_half and hi_half are output arrays
that parallel "operands". */
void
split_ti (operands, num, lo_half, hi_half)
rtx operands[];
int num;
rtx lo_half[], hi_half[];
{
while (num--)
{
rtx op = operands[num];
if (CONSTANT_P (op))
{
if (GET_CODE (op) == CONST_INT)
{
lo_half[num] = GEN_INT (trunc_int_for_mode (INTVAL (op), SImode));
hi_half[num] = (1 << (HOST_BITS_PER_WIDE_INT -1)) != 0 ? constm1_rtx : const0_rtx;
}
else if (GET_CODE (op) == CONST_DOUBLE && HOST_BITS_PER_WIDE_INT == 64)
{
lo_half[num] = GEN_INT (trunc_int_for_mode (CONST_DOUBLE_LOW (op), SImode));
hi_half[num] = GEN_INT (trunc_int_for_mode (CONST_DOUBLE_HIGH (op), SImode));
}
else
abort ();
}
else if (! reload_completed)
{
lo_half[num] = gen_lowpart (DImode, op);
hi_half[num] = gen_highpart (DImode, op);
}
else if (GET_CODE (op) == REG)
{
if (TARGET_64BIT)
abort();
lo_half[num] = gen_rtx_REG (DImode, REGNO (op));
hi_half[num] = gen_rtx_REG (DImode, REGNO (op) + 1);
}
else if (offsettable_memref_p (op))
{
lo_half[num] = adjust_address (op, DImode, 0);
hi_half[num] = adjust_address (op, DImode, 8);
}
else
abort ();
}
}
/* Output code to perform a 387 binary operation in INSN, one of PLUS,
MINUS, MULT or DIV. OPERANDS are the insn operands, where operands[3]
@ -6621,7 +6688,7 @@ ix86_expand_move (mode, operands)
else
{
if (GET_CODE (operands[0]) == MEM
&& (GET_MODE (operands[0]) == QImode
&& (PUSH_ROUNDING (GET_MODE_SIZE (mode)) != GET_MODE_SIZE (mode)
|| !push_operand (operands[0], mode))
&& GET_CODE (operands[1]) == MEM)
operands[1] = force_reg (mode, operands[1]);
@ -6630,6 +6697,15 @@ ix86_expand_move (mode, operands)
&& ! general_no_elim_operand (operands[1], mode))
operands[1] = copy_to_mode_reg (mode, operands[1]);
/* Force large constants in 64bit compilation into register
to get them CSEed. */
if (TARGET_64BIT && mode == DImode
&& immediate_operand (operands[1], mode)
&& !x86_64_zero_extended_value (operands[1])
&& !register_operand (operands[0], mode)
&& optimize && !reload_completed && !reload_in_progress)
operands[1] = copy_to_mode_reg (mode, operands[1]);
if (FLOAT_MODE_P (mode))
{
/* If we are loading a floating point constant to a register,
@ -8490,6 +8566,8 @@ ix86_split_to_parts (operand, parts, mode)
}
else
{
if (mode == TImode)
split_ti (&operand, 1, &parts[0], &parts[1]);
if (mode == XFmode || mode == TFmode)
{
if (REG_P (operand))
@ -8515,8 +8593,10 @@ ix86_split_to_parts (operand, parts, mode)
/* Do not use shift by 32 to avoid warning on 32bit systems. */
if (HOST_BITS_PER_WIDE_INT >= 64)
parts[0]
= GEN_INT (trunc_int_for_mode (l[0] + ((l[1] << 31) << 1),
SImode));
= GEN_INT (trunc_int_for_mode
((l[0] & (((HOST_WIDE_INT) 2 << 31) - 1))
+ ((((HOST_WIDE_INT)l[1]) << 31) << 1),
DImode));
else
parts[0] = immed_double_const (l[0], l[1], DImode);
parts[1] = GEN_INT (trunc_int_for_mode (l[2], SImode));
@ -10701,7 +10781,7 @@ x86_initialize_trampoline (tramp, fnaddr, cxt)
emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, offset)),
GEN_INT (trunc_int_for_mode (0xff49, HImode)));
emit_move_insn (gen_rtx_MEM (QImode, plus_constant (tramp, offset+2)),
GEN_INT (trunc_int_for_mode (0xe3, HImode)));
GEN_INT (trunc_int_for_mode (0xe3, QImode)));
offset += 3;
if (offset > TRAMPOLINE_SIZE)
abort();

View File

@ -58,6 +58,8 @@ struct processor_costs {
const int mult_init; /* cost of starting a multiply */
const int mult_bit; /* cost of multiply per each bit set */
const int divide; /* cost of a divide/mod */
int movsx; /* The cost of movsx operation. */
int movzx; /* The cost of movzx operation. */
const int large_insn; /* insns larger than this cost more */
const int move_ratio; /* The threshold of number of scalar
memory-to-memory move insns. */
@ -953,7 +955,8 @@ extern int ix86_arch;
((mode) == QImode || (mode) == HImode || (mode) == SImode \
|| (mode) == DImode \
|| (mode) == CQImode || (mode) == CHImode || (mode) == CSImode \
|| (mode) == CDImode)
|| (mode) == CDImode \
|| (TARGET_64BIT && ((mode) == TImode || (mode) == CTImode)))
/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */
@ -2427,6 +2430,10 @@ while (0)
case CONST: \
case LABEL_REF: \
case SYMBOL_REF: \
if (TARGET_64BIT && !x86_64_sign_extended_value (RTX)) \
return 3; \
if (TARGET_64BIT && !x86_64_zero_extended_value (RTX)) \
return 2; \
return flag_pic && SYMBOLIC_CONST (RTX) ? 1 : 0; \
\
case CONST_DOUBLE: \
@ -2456,9 +2463,24 @@ while (0)
assumptions are adequate for the target machine. */
#define RTX_COSTS(X,CODE,OUTER_CODE) \
case ZERO_EXTEND: \
/* The zero extensions is often completely free on x86_64, so make \
it as cheap as possible. */ \
if (TARGET_64BIT && GET_MODE (X) == DImode \
&& GET_MODE (XEXP (X, 0)) == SImode) \
{ \
total = 1; goto egress_rtx_costs; \
} \
else \
TOPLEVEL_COSTS_N_INSNS (TARGET_ZERO_EXTEND_WITH_AND ? \
ix86_cost->add : ix86_cost->movzx); \
break; \
case SIGN_EXTEND: \
TOPLEVEL_COSTS_N_INSNS (ix86_cost->movsx); \
break; \
case ASHIFT: \
if (GET_CODE (XEXP (X, 1)) == CONST_INT \
&& GET_MODE (XEXP (X, 0)) == SImode) \
&& (GET_MODE (XEXP (X, 0)) != DImode || TARGET_64BIT)) \
{ \
HOST_WIDE_INT value = INTVAL (XEXP (X, 1)); \
if (value == 1) \
@ -2472,7 +2494,7 @@ while (0)
case ASHIFTRT: \
case LSHIFTRT: \
case ROTATERT: \
if (GET_MODE (XEXP (X, 0)) == DImode) \
if (!TARGET_64BIT && GET_MODE (XEXP (X, 0)) == DImode) \
{ \
if (GET_CODE (XEXP (X, 1)) == CONST_INT) \
{ \
@ -2562,7 +2584,7 @@ while (0)
case IOR: \
case XOR: \
case MINUS: \
if (GET_MODE (X) == DImode) \
if (!TARGET_64BIT && GET_MODE (X) == DImode) \
return (COSTS_N_INSNS (ix86_cost->add) * 2 \
+ (rtx_cost (XEXP (X, 0), OUTER_CODE) \
<< (GET_MODE (XEXP (X, 0)) != DImode)) \
@ -2572,7 +2594,7 @@ while (0)
/* fall through */ \
case NEG: \
case NOT: \
if (GET_MODE (X) == DImode) \
if (!TARGET_64BIT && GET_MODE (X) == DImode) \
TOPLEVEL_COSTS_N_INSNS (ix86_cost->add * 2); \
TOPLEVEL_COSTS_N_INSNS (ix86_cost->add); \
\
@ -2961,7 +2983,7 @@ do { long l; \
*/
#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
fprintf (FILE, "%s%s%d\n", ASM_LONG, LPREFIX, VALUE)
fprintf (FILE, "%s%s%d\n", TARGET_64BIT ? ASM_QUAD : ASM_LONG, LPREFIX, VALUE)
/* This is how to output an element of a case-vector that is relative.
We don't use these on the 386 yet, because the ATT assembler can't do

View File

@ -8106,6 +8106,12 @@
(const_int 0)))]
"TARGET_64BIT
&& ix86_match_ccmode (insn, CCNOmode)
/* The code bellow cannot deal with constants outside HOST_WIDE_INT. */
&& INTVAL (operands[1]) + INTVAL (operands[2]) < HOST_BITS_PER_WIDE_INT
/* Ensure that resulting mask is zero or sign extended operand. */
&& (INTVAL (operands[1]) + INTVAL (operands[2]) <= 32
|| (INTVAL (operands[1]) + INTVAL (operands[2]) == 64
&& INTVAL (operands[1]) > 32))
&& (GET_MODE (operands[0]) == SImode
|| GET_MODE (operands[0]) == DImode
|| GET_MODE (operands[0]) == HImode
@ -13114,7 +13120,8 @@
{
if (TARGET_64BIT)
operands[0] = expand_simple_binop (Pmode, PLUS, operands[0],
operands[1], NULL_RTX, 0,
gen_rtx_LABEL_REF (Pmode, operands[1]),
NULL_RTX, 0,
OPTAB_DIRECT);
else
{
@ -15638,11 +15645,11 @@
;; Conditional move instructions.
(define_expand "movdicc_rex64"
(define_expand "movdicc"
[(set (match_operand:DI 0 "register_operand" "")
(if_then_else:DI (match_operand 1 "comparison_operator" "")
(match_operand:DI 2 "x86_64_general_operand" "")
(match_operand:DI 3 "x86_64_general_operand" "")))]
(match_operand:DI 2 "general_operand" "")
(match_operand:DI 3 "general_operand" "")))]
"TARGET_64BIT"
"if (!ix86_expand_int_movcc (operands)) FAIL; DONE;")
@ -17653,8 +17660,13 @@
(define_expand "movti"
[(set (match_operand:TI 0 "general_operand" "")
(match_operand:TI 1 "general_operand" ""))]
"TARGET_SSE"
"TARGET_SSE || TARGET_64BIT"
{
if (TARGET_64BIT)
{
ix86_expand_move (TImode, operands);
DONE;
}
/* For constants other than zero into memory. We do not know how the
instructions used to build constants modify the upper 64 bits
of the register, once we have that information we may be able
@ -17950,12 +17962,33 @@
(define_insn "movti_internal"
[(set (match_operand:TI 0 "nonimmediate_operand" "=x,m")
(match_operand:TI 1 "general_operand" "xm,x"))]
"TARGET_SSE"
"TARGET_SSE && !TARGET_64BIT"
"@
movaps\t{%1, %0|%0, %1}
movaps\t{%1, %0|%0, %1}"
[(set_attr "type" "sse")])
(define_insn "*movti_rex64"
[(set (match_operand:DI 0 "nonimmediate_operand" "=r,o,mx,x")
(match_operand:DI 1 "general_operand" "riFo,riF,x,m"))]
"TARGET_64BIT
&& (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
"@
#
#
movaps\\t{%1, %0|%0, %1}
movaps\\t{%1, %0|%0, %1}"
[(set_attr "type" "*,*,sse,sse")
(set_attr "mode" "TI")])
(define_split
[(set (match_operand:TI 0 "nonimmediate_operand" "")
(match_operand:TI 1 "general_operand" ""))]
"reload_completed && GENERAL_REG_P (operands[0])
&& GENERAL_REG_P (operands[1])"
[(const_int 0)]
"ix86_split_long_move (operands); DONE;")
;; These two patterns are useful for specifying exactly whether to use
;; movaps or movups
(define_insn "sse_movaps"

View File

@ -39,7 +39,7 @@ Boston, MA 02111-1307, USA. */
done. */
#undef LINK_SPEC
#define LINK_SPEC "%{!m32:-m elf_x86_64} %{m32:-m elf_i386} {shared:-shared} \
#define LINK_SPEC "%{!m32:-m elf_x86_64} %{m32:-m elf_i386} %{shared:-shared} \
%{!shared: \
%{!static: \
%{rdynamic:-export-dynamic} \