mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-01-27 08:24:07 +08:00
entered into RCS
From-SVN: r782
This commit is contained in:
parent
e1fde2b5bc
commit
d3797078d4
@ -276,3 +276,303 @@ rev_cond_name (op)
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
vax_float_literal(c)
|
||||
register rtx c;
|
||||
{
|
||||
register enum machine_mode mode;
|
||||
int i;
|
||||
union {double d; int i[2];} val;
|
||||
|
||||
if (GET_CODE (c) != CONST_DOUBLE)
|
||||
return 0;
|
||||
|
||||
mode = GET_MODE (c);
|
||||
|
||||
if (c == const_tiny_rtx[(int) mode][0]
|
||||
|| c == const_tiny_rtx[(int) mode][1]
|
||||
|| c == const_tiny_rtx[(int) mode][2])
|
||||
return 1;
|
||||
|
||||
#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
|
||||
|
||||
val.i[0] = CONST_DOUBLE_LOW (c);
|
||||
val.i[1] = CONST_DOUBLE_HIGH (c);
|
||||
|
||||
for (i = 0; i < 7; i ++)
|
||||
if (val.d == 1 << i || val.d == 1 / (1 << i))
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Return the cost in cycles of a memory address, relative to register
|
||||
indirect.
|
||||
|
||||
Each of the following adds the indicated number of cycles:
|
||||
|
||||
1 - symbolic address
|
||||
1 - pre-decrement
|
||||
1 - indexing and/or offset(register)
|
||||
2 - indirect */
|
||||
|
||||
|
||||
int vax_address_cost(addr)
|
||||
register rtx addr;
|
||||
{
|
||||
int reg = 0, indexed = 0, indir = 0, offset = 0, predec = 0;
|
||||
rtx plus_op0 = 0, plus_op1 = 0;
|
||||
restart:
|
||||
switch (GET_CODE (addr))
|
||||
{
|
||||
case PRE_DEC:
|
||||
predec = 1;
|
||||
case REG:
|
||||
case SUBREG:
|
||||
case POST_INC:
|
||||
reg = 1;
|
||||
break;
|
||||
case MULT:
|
||||
indexed = 1; /* 2 on VAX 2 */
|
||||
break;
|
||||
case CONST_INT:
|
||||
/* byte offsets cost nothing (on a VAX 2, they cost 1 cycle) */
|
||||
if (offset == 0)
|
||||
offset = (unsigned)(INTVAL(addr)+128) > 256;
|
||||
break;
|
||||
case CONST:
|
||||
case SYMBOL_REF:
|
||||
offset = 1; /* 2 on VAX 2 */
|
||||
break;
|
||||
case LABEL_REF: /* this is probably a byte offset from the pc */
|
||||
if (offset == 0)
|
||||
offset = 1;
|
||||
break;
|
||||
case PLUS:
|
||||
if (plus_op0)
|
||||
plus_op1 = XEXP (addr, 0);
|
||||
else
|
||||
plus_op0 = XEXP (addr, 0);
|
||||
addr = XEXP (addr, 1);
|
||||
goto restart;
|
||||
case MEM:
|
||||
indir = 2; /* 3 on VAX 2 */
|
||||
addr = XEXP (addr, 0);
|
||||
goto restart;
|
||||
}
|
||||
|
||||
/* Up to 3 things can be added in an address. They are stored in
|
||||
plus_op0, plus_op1, and addr. */
|
||||
|
||||
if (plus_op0)
|
||||
{
|
||||
addr = plus_op0;
|
||||
plus_op0 = 0;
|
||||
goto restart;
|
||||
}
|
||||
if (plus_op1)
|
||||
{
|
||||
addr = plus_op1;
|
||||
plus_op1 = 0;
|
||||
goto restart;
|
||||
}
|
||||
/* Indexing and register+offset can both be used (except on a VAX 2)
|
||||
without increasing execution time over either one alone. */
|
||||
if (reg && indexed && offset)
|
||||
return reg + indir + offset + predec;
|
||||
return reg + indexed + indir + offset + predec;
|
||||
}
|
||||
|
||||
|
||||
/* Cost of an expression on a VAX. This version has costs tuned for the
|
||||
CVAX chip (found in the VAX 3 series) with comments for variations on
|
||||
other models. */
|
||||
|
||||
int
|
||||
vax_rtx_cost (x)
|
||||
register rtx x;
|
||||
{
|
||||
register enum rtx_code code = GET_CODE (x);
|
||||
enum machine_mode mode = GET_MODE (x);
|
||||
register int c;
|
||||
int i = 0; /* may be modified in switch */
|
||||
char *fmt = GET_RTX_FORMAT (code); /* may be modified in switch */
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case POST_INC:
|
||||
return 2;
|
||||
case PRE_DEC:
|
||||
return 3;
|
||||
case MULT:
|
||||
switch (mode)
|
||||
{
|
||||
case DFmode:
|
||||
c = 16; /* 4 on VAX 9000 */
|
||||
break;
|
||||
case SFmode:
|
||||
c = 9; /* 4 on VAX 9000, 12 on VAX 2 */
|
||||
break;
|
||||
case DImode:
|
||||
c = 16; /* 6 on VAX 9000, 28 on VAX 2 */
|
||||
break;
|
||||
case SImode:
|
||||
case HImode:
|
||||
case QImode:
|
||||
c = 10; /* 3-4 on VAX 9000, 20-28 on VAX 2 */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case UDIV:
|
||||
c = 17;
|
||||
break;
|
||||
case DIV:
|
||||
if (mode == DImode)
|
||||
c = 30; /* highly variable */
|
||||
else if (mode == DFmode)
|
||||
/* divide takes 28 cycles if the result is not zero, 13 otherwise */
|
||||
c = 24;
|
||||
else
|
||||
c = 11; /* 25 on VAX 2 */
|
||||
break;
|
||||
case MOD:
|
||||
c = 23;
|
||||
break;
|
||||
case UMOD:
|
||||
c = 29;
|
||||
break;
|
||||
case FLOAT:
|
||||
c = 6 + (mode == DFmode) + (GET_MODE (XEXP (x, 0)) != SImode);
|
||||
/* 4 on VAX 9000 */
|
||||
break;
|
||||
case FIX:
|
||||
c = 7; /* 17 on VAX 2 */
|
||||
break;
|
||||
case LSHIFT:
|
||||
case ASHIFT:
|
||||
case LSHIFTRT:
|
||||
case ASHIFTRT:
|
||||
if (mode == DImode)
|
||||
c = 12;
|
||||
else
|
||||
c = 10; /* 6 on VAX 9000 */
|
||||
break;
|
||||
case ROTATE:
|
||||
case ROTATERT:
|
||||
c = 6; /* 5 on VAX 2, 4 on VAX 9000 */
|
||||
if (GET_CODE (XEXP (x, 1)) == CONST_INT)
|
||||
fmt = "e"; /* all constant rotate counts are short */
|
||||
break;
|
||||
case PLUS:
|
||||
/* Check for small negative integer operand: subl2 can be used with
|
||||
a short positive constant instead. */
|
||||
if (GET_CODE (XEXP (x, 1)) == CONST_INT)
|
||||
if ((unsigned)(INTVAL (XEXP (x, 1)) + 63) < 127)
|
||||
fmt = "e";
|
||||
case MINUS:
|
||||
c = (mode == DFmode) ? 13 : 8; /* 6/8 on VAX 9000, 16/15 on VAX 2 */
|
||||
case IOR:
|
||||
case XOR:
|
||||
c = 3;
|
||||
break;
|
||||
case AND:
|
||||
/* AND is special because the first operand is complemented. */
|
||||
c = 3;
|
||||
if (GET_CODE (XEXP (x, 0)) == CONST_INT)
|
||||
{
|
||||
if ((unsigned)~INTVAL (XEXP (x, 0)) > 63)
|
||||
c = 4;
|
||||
fmt = "e";
|
||||
i = 1;
|
||||
}
|
||||
break;
|
||||
case NEG:
|
||||
if (mode == DFmode)
|
||||
return 9;
|
||||
else if (mode == SFmode)
|
||||
return 6;
|
||||
else if (mode == DImode)
|
||||
return 4;
|
||||
case NOT:
|
||||
return 2;
|
||||
case ZERO_EXTRACT:
|
||||
case SIGN_EXTRACT:
|
||||
c = 15;
|
||||
break;
|
||||
case MEM:
|
||||
if (mode == DImode || mode == DFmode)
|
||||
c = 5; /* 7 on VAX 2 */
|
||||
else
|
||||
c = 3; /* 4 on VAX 2 */
|
||||
x = XEXP (x, 0);
|
||||
if (GET_CODE (x) == REG || GET_CODE (x) == POST_INC)
|
||||
return c;
|
||||
return c + vax_address_cost (x);
|
||||
default:
|
||||
c = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* Now look inside the expression. Operands which are not registers or
|
||||
short constants add to the cost.
|
||||
|
||||
FMT and I may have been adjusted in the switch above for instructions
|
||||
which require special handling */
|
||||
|
||||
while (*fmt++ == 'e')
|
||||
{
|
||||
register rtx op = XEXP (x, i++);
|
||||
code = GET_CODE (op);
|
||||
|
||||
/* A NOT is likely to be found as the first operand of an AND
|
||||
(in which case the relevant cost is of the operand inside
|
||||
the not) and not likely to be found anywhere else. */
|
||||
if (code == NOT)
|
||||
op = XEXP (op, 0), code = GET_CODE (op);
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case CONST_INT:
|
||||
if ((unsigned)INTVAL (op) > 63 && GET_MODE (x) != QImode)
|
||||
c += 1; /* 2 on VAX 2 */
|
||||
break;
|
||||
case CONST:
|
||||
case LABEL_REF:
|
||||
case SYMBOL_REF:
|
||||
c += 1; /* 2 on VAX 2 */
|
||||
break;
|
||||
case CONST_DOUBLE:
|
||||
if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT)
|
||||
{
|
||||
/* Registers are faster than floating point constants -- even
|
||||
those constants which can be encoded in a single byte. */
|
||||
if (vax_float_literal (op))
|
||||
c++;
|
||||
else
|
||||
c += (GET_MODE (x) == DFmode) ? 3 : 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (CONST_DOUBLE_HIGH (op) != 0
|
||||
|| (unsigned)CONST_DOUBLE_LOW (op) > 63)
|
||||
c += 2;
|
||||
}
|
||||
break;
|
||||
case MEM:
|
||||
c += 1; /* 2 on VAX 2 */
|
||||
if (GET_CODE (XEXP (op, 0)) != REG)
|
||||
c += vax_address_cost (XEXP (op, 0));
|
||||
break;
|
||||
case REG:
|
||||
case SUBREG:
|
||||
break;
|
||||
default:
|
||||
c += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user