Commit ef6257cd by Jan Hubicka Committed by Jan Hubicka

i386.md (floatdi?f): Avoid usinf of SSE instructions if TARGET_64BIT is false.

	* i386.md (floatdi?f): Avoid usinf of SSE instructions
	if TARGET_64BIT is false.
	(floatdi?f_i386_only): New insn.
	(floatdi?f_i386): Disable for !TARGET_64BIT.

	* (min?f, max?f splitters): Handle case where
	operands are cross-matched.

	* i386.h (HI_REGISTER_NAMES): Remove redundant definition
	(MMX_REGISTER_NAMES): Kill.
	(PRINT_OPERAND): Fix comment.
	(PRINT_REG): Likewise.
	* i386.c (print_reg): Kill support for 'm' CODE; simplify.
	(print_operand): Update comment; kill 'm'.

	* i386.c (x86_branch_hints): New global variable
	(print_operand): Support outputting of branch prediction hints.
	* i386.md (conditional jump patterns): Add branch prediction hints
	to the template.
	* i386.h (x86_branch_hints): Declare
	(TARGET_BRANCH_PREDICTION_HINTS): New macro.
	(PRINT_OPERAND_FUNCT_VALID_P): New.
	* final.c (final_forward_branch_p): New function.

From-SVN: r42945
parent 3b8fd08f
Wed Jun 6 14:51:05 CEST 2001 Jan Hubicka <jh@suse.cz>
* i386.md (floatdi?f): Avoid usinf of SSE instructions
if TARGET_64BIT is false.
(floatdi?f_i386_only): New insn.
(floatdi?f_i386): Disable for !TARGET_64BIT.
* (min?f, max?f splitters): Handle case where
operands are cross-matched.
* i386.h (HI_REGISTER_NAMES): Remove redundant definition
(MMX_REGISTER_NAMES): Kill.
(PRINT_OPERAND): Fix comment.
(PRINT_REG): Likewise.
* i386.c (print_reg): Kill support for 'm' CODE; simplify.
(print_operand): Update comment; kill 'm'.
* i386.c (x86_branch_hints): New global variable
(print_operand): Support outputting of branch prediction hints.
* i386.md (conditional jump patterns): Add branch prediction hints
to the template.
* i386.h (x86_branch_hints): Declare
(TARGET_BRANCH_PREDICTION_HINTS): New macro.
(PRINT_OPERAND_FUNCT_VALID_P): New.
* final.c (final_forward_branch_p): New function.
2001-06-06 Richard Henderson <rth@redhat.com>
* flow.c (mark_used_reg): Clean up looping over multiple hard
......
......@@ -290,6 +290,7 @@ const int x86_use_bit_test = m_386;
const int x86_unroll_strlen = m_486 | m_PENT | m_PPRO | m_ATHLON | m_K6;
const int x86_cmove = m_PPRO | m_ATHLON | m_PENT4;
const int x86_deep_branch = m_PPRO | m_K6 | m_ATHLON | m_PENT4;
const int x86_branch_hints = m_PENT4;
const int x86_use_sahf = m_PPRO | m_K6 | m_PENT4;
const int x86_partial_reg_stall = m_PPRO;
const int x86_use_loop = m_K6;
......@@ -3796,7 +3797,7 @@ print_reg (x, code, file)
if (ASSEMBLER_DIALECT == 0 || USER_LABEL_PREFIX[0] == 0)
putc ('%', file);
if (code == 'w')
if (code == 'w' || MMX_REG_P (x))
code = 2;
else if (code == 'b')
code = 1;
......@@ -3808,8 +3809,6 @@ print_reg (x, code, file)
code = 3;
else if (code == 'h')
code = 0;
else if (code == 'm' || MMX_REG_P (x))
code = 5;
else
code = GET_MODE_SIZE (GET_MODE (x));
......@@ -3821,7 +3820,7 @@ print_reg (x, code, file)
abort ();
switch (code)
{
case 5:
case 0:
error ("Extended registers have no high halves\n");
break;
case 1:
......@@ -3844,9 +3843,6 @@ print_reg (x, code, file)
}
switch (code)
{
case 5:
fputs (hi_reg_name[REGNO (x)], file);
break;
case 3:
if (STACK_TOP_P (x))
{
......@@ -3879,6 +3875,7 @@ print_reg (x, code, file)
L,W,B,Q,S,T -- print the opcode suffix for specified size of operand.
C -- print opcode suffix for set/cmov insn.
c -- like C, but print reversed condition
F,f -- likewise, but for floating-point.
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)
......@@ -3891,10 +3888,11 @@ print_reg (x, code, file)
w -- likewise, print the HImode name of the register.
k -- likewise, print the SImode name of the register.
q -- likewise, print the DImode name of the register.
h -- print the QImode name for a "high" register, either ah, bh, ch or dh.
y -- print "st(0)" instead of "st" as a register.
m -- print "st(n)" as an mmx register.
h -- print the QImode name for a "high" register, either ah, bh, ch or dh.
y -- print "st(0)" instead of "st" as a register.
D -- print condition for SSE cmp instruction.
P -- if PIC, print an @PLT suffix.
X -- don't print any sort of PIC '@' suffix for a symbol.
*/
void
......@@ -4017,7 +4015,6 @@ print_operand (file, x, code)
case 'q':
case 'h':
case 'y':
case 'm':
case 'X':
case 'P':
break;
......@@ -4085,7 +4082,39 @@ print_operand (file, x, code)
case 'f':
put_condition_code (GET_CODE (x), GET_MODE (XEXP (x, 0)), 1, 1, file);
return;
case '+':
{
rtx x;
if (!optimize || optimize_size || !TARGET_BRANCH_PREDICTION_HINTS)
return;
x = find_reg_note (current_output_insn, REG_BR_PROB, 0);
if (x)
{
int pred_val = INTVAL (XEXP (x, 0));
if (pred_val < REG_BR_PROB_BASE * 45 / 100
|| pred_val > REG_BR_PROB_BASE * 55 / 100)
{
int taken = pred_val > REG_BR_PROB_BASE / 2;
int cputaken = final_forward_branch_p (current_output_insn) == 0;
/* Emit hints only in the case default branch prediction
heruistics would fail. */
if (taken != cputaken)
{
/* We use 3e (DS) prefix for taken branches and
2e (CS) prefix for not taken branches. */
if (taken)
fputs ("ds ; ", file);
else
fputs ("cs ; ", file);
}
}
}
return;
}
default:
{
char str[50];
......
......@@ -202,7 +202,7 @@ extern int target_flags;
#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;
extern const int x86_branch_hints, x86_unroll_strlen;
extern const int x86_double_with_add, x86_partial_reg_stall, x86_movx;
extern const int x86_use_loop, x86_use_fiop, x86_use_mov0;
extern const int x86_use_cltd, x86_read_modify_write;
......@@ -222,6 +222,7 @@ extern const int x86_partial_reg_dependency, x86_memory_mismatch_stall;
safe to enable all CMOVE instructions. */
#define TARGET_CMOVE ((x86_cmove & (1 << ix86_arch)) || TARGET_SSE)
#define TARGET_DEEP_BRANCH_PREDICTION (x86_deep_branch & CPUMASK)
#define TARGET_BRANCH_PREDICTION_HINTS (x86_branch_hints & CPUMASK)
#define TARGET_DOUBLE_WITH_ADD (x86_double_with_add & CPUMASK)
#define TARGET_USE_SAHF ((x86_use_sahf & CPUMASK) && !TARGET_64BIT)
#define TARGET_MOVX (x86_movx & CPUMASK)
......@@ -2755,11 +2756,6 @@ while (0)
For float regs, the stack top is sometimes referred to as "%st(0)"
instead of just "%st". PRINT_REG handles this with the "y" code. */
#define HI_REGISTER_NAMES \
{"ax","dx","cx","bx","si","di","bp","sp", \
"st","st(1)","st(2)","st(3)","st(4)","st(5)","st(6)","st(7)","", \
"flags","fpsr", "dirflag", "frame" }
#undef HI_REGISTER_NAMES
#define HI_REGISTER_NAMES \
{"ax","dx","cx","bx","si","di","bp","sp", \
......@@ -2798,9 +2794,6 @@ number as al, and ax.
#define QI_HIGH_REGISTER_NAMES \
{"ah", "dh", "ch", "bh", }
#define MMX_REGISTER_NAMES \
{0,0,0,0,0,0,0,0,"mm0","mm1","mm2","mm3","mm4","mm5","mm6","mm7"}
/* How to renumber registers for dbx and gdb. */
#define DBX_REGISTER_NUMBER(n) \
......@@ -2970,33 +2963,19 @@ do { long l; \
/* Print operand X (an rtx) in assembler syntax to file FILE.
CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
The CODE z takes the size of operand from the following digit, and
outputs b,w,or l respectively.
On the 80386, we use several such letters:
f -- float insn (print a CONST_DOUBLE as a float rather than in hex).
L,W,B,Q,S,T -- print the opcode suffix for specified size of operand.
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)
A -- print an absolute memory reference.
P -- if PIC, print an @PLT suffix.
X -- don't print any sort of PIC '@' suffix for a symbol.
s -- ??? something to do with double shifts. not actually used, afaik.
C -- print a conditional move suffix corresponding to the op code.
c -- likewise, but reverse the condition.
F,f -- likewise, but for floating-point. */
Effect of various CODE letters is described in i386.c near
print_operand function. */
#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
((CODE) == '*')
((CODE) == '*' || (CODE) == '+')
/* Print the name of a register based on its machine mode and number.
If CODE is 'w', pretend the mode is HImode.
If CODE is 'b', pretend the mode is QImode.
If CODE is 'k', pretend the mode is SImode.
If CODE is 'd', pretend the mode is DImode.
If CODE is 'q', pretend the mode is DImode.
If CODE is 'h', pretend the reg is the `high' byte register.
If CODE is 'y', print "st(0)" instead of "st", if the reg is stack op. */
If CODE is 'y', print "st(0)" instead of "st", if the reg is stack op. */
#define PRINT_REG(X, CODE, FILE) \
print_reg (X, CODE, FILE)
......
......@@ -4086,6 +4086,25 @@ leaf_function_p ()
return 1;
}
/* Return 1 if branch is an forward branch.
Uses insn_shuid array, so it works only in the final pass. May be used by
output templates to customary add branch prediction hints.
*/
int
final_forward_branch_p (insn)
rtx insn;
{
int insn_id, label_id;
if (!uid_shuid)
abort ();
insn_id = INSN_SHUID (insn);
label_id = INSN_SHUID (JUMP_LABEL (insn));
/* We've hit some insns that does not have id information available. */
if (!insn_id || !label_id)
abort ();
return insn_id < label_id;
}
/* On some machines, a function with no call insns
can run faster if it doesn't create its own register window.
When output, the leaf function should use only the "output"
......
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