above this default. */
*cost = COSTS_N_INSNS (1);
- /* TODO: The cost infrastructure currently does not handle
- vector operations. Assume that all vector operations
- are equally expensive. */
- if (VECTOR_MODE_P (mode))
- {
- if (speed)
- *cost += extra_cost->vect.alu;
- return true;
- }
-
switch (code)
{
case SET:
if (speed)
{
rtx address = XEXP (op0, 0);
- if (GET_MODE_CLASS (mode) == MODE_INT)
+ if (VECTOR_MODE_P (mode))
+ *cost += extra_cost->ldst.storev;
+ else if (GET_MODE_CLASS (mode) == MODE_INT)
*cost += extra_cost->ldst.store;
else if (mode == SFmode)
*cost += extra_cost->ldst.storef;
/* Fall through. */
case REG:
+ /* The cost is one per vector-register copied. */
+ if (VECTOR_MODE_P (GET_MODE (op0)) && REG_P (op1))
+ {
+ int n_minus_1 = (GET_MODE_SIZE (GET_MODE (op0)) - 1)
+ / GET_MODE_SIZE (V4SImode);
+ *cost = COSTS_N_INSNS (n_minus_1 + 1);
+ }
/* const0_rtx is in general free, but we will use an
instruction to set a register to 0. */
- if (REG_P (op1) || op1 == const0_rtx)
- {
- /* The cost is 1 per register copied. */
- int n_minus_1 = (GET_MODE_SIZE (GET_MODE (op0)) - 1)
+ else if (REG_P (op1) || op1 == const0_rtx)
+ {
+ /* The cost is 1 per register copied. */
+ int n_minus_1 = (GET_MODE_SIZE (GET_MODE (op0)) - 1)
/ UNITS_PER_WORD;
- *cost = COSTS_N_INSNS (n_minus_1 + 1);
- }
+ *cost = COSTS_N_INSNS (n_minus_1 + 1);
+ }
else
/* Cost is just the cost of the RHS of the set. */
*cost += rtx_cost (op1, SET, 1, speed);
approximation for the additional cost of the addressing
mode. */
rtx address = XEXP (x, 0);
- if (GET_MODE_CLASS (mode) == MODE_INT)
+ if (VECTOR_MODE_P (mode))
+ *cost += extra_cost->ldst.loadv;
+ else if (GET_MODE_CLASS (mode) == MODE_INT)
*cost += extra_cost->ldst.load;
else if (mode == SFmode)
*cost += extra_cost->ldst.loadf;
case NEG:
op0 = XEXP (x, 0);
+ if (VECTOR_MODE_P (mode))
+ {
+ if (speed)
+ {
+ /* FNEG. */
+ *cost += extra_cost->vect.alu;
+ }
+ return false;
+ }
+
if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
{
if (GET_RTX_CLASS (GET_CODE (op0)) == RTX_COMPARE
case CLRSB:
case CLZ:
if (speed)
- *cost += extra_cost->alu.clz;
+ {
+ if (VECTOR_MODE_P (mode))
+ *cost += extra_cost->vect.alu;
+ else
+ *cost += extra_cost->alu.clz;
+ }
return false;
return false;
}
+ if (VECTOR_MODE_P (mode))
+ {
+ /* Vector compare. */
+ if (speed)
+ *cost += extra_cost->vect.alu;
+
+ if (aarch64_float_const_zero_rtx_p (op1))
+ {
+ /* Vector cm (eq|ge|gt|lt|le) supports constant 0.0 for no extra
+ cost. */
+ return true;
+ }
+ return false;
+ }
return false;
case MINUS:
if (speed)
{
- if (GET_MODE_CLASS (mode) == MODE_INT)
- /* SUB(S). */
- *cost += extra_cost->alu.arith;
+ if (VECTOR_MODE_P (mode))
+ {
+ /* Vector SUB. */
+ *cost += extra_cost->vect.alu;
+ }
+ else if (GET_MODE_CLASS (mode) == MODE_INT)
+ {
+ /* SUB(S). */
+ *cost += extra_cost->alu.arith;
+ }
else if (GET_MODE_CLASS (mode) == MODE_FLOAT)
- /* FSUB. */
- *cost += extra_cost->fp[mode == DFmode].addsub;
+ {
+ /* FSUB. */
+ *cost += extra_cost->fp[mode == DFmode].addsub;
+ }
}
return true;
}
if (speed)
{
- if (GET_MODE_CLASS (mode) == MODE_INT)
- /* ADD. */
- *cost += extra_cost->alu.arith;
+ if (VECTOR_MODE_P (mode))
+ {
+ /* Vector ADD. */
+ *cost += extra_cost->vect.alu;
+ }
+ else if (GET_MODE_CLASS (mode) == MODE_INT)
+ {
+ /* ADD. */
+ *cost += extra_cost->alu.arith;
+ }
else if (GET_MODE_CLASS (mode) == MODE_FLOAT)
- /* FADD. */
- *cost += extra_cost->fp[mode == DFmode].addsub;
+ {
+ /* FADD. */
+ *cost += extra_cost->fp[mode == DFmode].addsub;
+ }
}
return true;
}
*cost = COSTS_N_INSNS (1);
if (speed)
- *cost += extra_cost->alu.rev;
-
+ {
+ if (VECTOR_MODE_P (mode))
+ *cost += extra_cost->vect.alu;
+ else
+ *cost += extra_cost->alu.rev;
+ }
return false;
case IOR:
{
*cost = COSTS_N_INSNS (1);
- if (speed)
- *cost += extra_cost->alu.rev;
-
- return true;
+ if (speed)
+ {
+ if (VECTOR_MODE_P (mode))
+ *cost += extra_cost->vect.alu;
+ else
+ *cost += extra_cost->alu.rev;
+ }
+ return true;
}
if (aarch64_extr_rtx_p (x, &op0, &op1))
op0 = XEXP (x, 0);
op1 = XEXP (x, 1);
+ if (VECTOR_MODE_P (mode))
+ {
+ if (speed)
+ *cost += extra_cost->vect.alu;
+ return true;
+ }
+
if (code == AND
&& GET_CODE (op0) == MULT
&& CONST_INT_P (XEXP (op0, 1))
x = XEXP (x, 0);
op0 = aarch64_strip_shift (x);
+ if (VECTOR_MODE_P (mode))
+ {
+ /* Vector NOT. */
+ *cost += extra_cost->vect.alu;
+ return false;
+ }
+
/* MVN-shifted-reg. */
if (op0 != x)
{
return true;
}
- /* UXTB/UXTH. */
if (speed)
- *cost += extra_cost->alu.extend;
-
+ {
+ if (VECTOR_MODE_P (mode))
+ {
+ /* UMOV. */
+ *cost += extra_cost->vect.alu;
+ }
+ else
+ {
+ /* UXTB/UXTH. */
+ *cost += extra_cost->alu.extend;
+ }
+ }
return false;
case SIGN_EXTEND:
}
if (speed)
- *cost += extra_cost->alu.extend;
+ {
+ if (VECTOR_MODE_P (mode))
+ *cost += extra_cost->vect.alu;
+ else
+ *cost += extra_cost->alu.extend;
+ }
return false;
case ASHIFT:
if (CONST_INT_P (op1))
{
- /* LSL (immediate), UBMF, UBFIZ and friends. These are all
- aliases. */
if (speed)
- *cost += extra_cost->alu.shift;
+ {
+ if (VECTOR_MODE_P (mode))
+ {
+ /* Vector shift (immediate). */
+ *cost += extra_cost->vect.alu;
+ }
+ else
+ {
+ /* LSL (immediate), UBMF, UBFIZ and friends. These are all
+ aliases. */
+ *cost += extra_cost->alu.shift;
+ }
+ }
/* We can incorporate zero/sign extend for free. */
if (GET_CODE (op0) == ZERO_EXTEND
}
else
{
- /* LSLV. */
if (speed)
- *cost += extra_cost->alu.shift_reg;
-
+ {
+ if (VECTOR_MODE_P (mode))
+ {
+ /* Vector shift (register). */
+ *cost += extra_cost->vect.alu;
+ }
+ else
+ {
+ /* LSLV. */
+ *cost += extra_cost->alu.shift_reg;
+ }
+ }
return false; /* All arguments need to be in registers. */
}
{
/* ASR (immediate) and friends. */
if (speed)
- *cost += extra_cost->alu.shift;
+ {
+ if (VECTOR_MODE_P (mode))
+ *cost += extra_cost->vect.alu;
+ else
+ *cost += extra_cost->alu.shift;
+ }
*cost += rtx_cost (op0, (enum rtx_code) code, 0, speed);
return true;
/* ASR (register) and friends. */
if (speed)
- *cost += extra_cost->alu.shift_reg;
-
+ {
+ if (VECTOR_MODE_P (mode))
+ *cost += extra_cost->vect.alu;
+ else
+ *cost += extra_cost->alu.shift_reg;
+ }
return false; /* All arguments need to be in registers. */
}
case SIGN_EXTRACT:
/* UBFX/SBFX. */
if (speed)
- *cost += extra_cost->alu.bfx;
+ {
+ if (VECTOR_MODE_P (mode))
+ *cost += extra_cost->vect.alu;
+ else
+ *cost += extra_cost->alu.bfx;
+ }
/* We can trust that the immediates used will be correct (there
are no by-register forms), so we need only cost op0. */
case UMOD:
if (speed)
{
- if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
+ if (VECTOR_MODE_P (mode))
+ *cost += extra_cost->vect.alu;
+ else if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
*cost += (extra_cost->mult[GET_MODE (x) == DImode].add
+ extra_cost->mult[GET_MODE (x) == DImode].idiv);
else if (GET_MODE (x) == DFmode)
case SQRT:
if (speed)
{
- if (GET_MODE_CLASS (mode) == MODE_INT)
+ if (VECTOR_MODE_P (mode))
+ *cost += extra_cost->vect.alu;
+ else if (GET_MODE_CLASS (mode) == MODE_INT)
/* There is no integer SQRT, so only DIV and UDIV can get
here. */
*cost += extra_cost->mult[mode == DImode].idiv;
op2 = XEXP (x, 2);
if (speed)
- *cost += extra_cost->fp[mode == DFmode].fma;
+ {
+ if (VECTOR_MODE_P (mode))
+ *cost += extra_cost->vect.alu;
+ else
+ *cost += extra_cost->fp[mode == DFmode].fma;
+ }
/* FMSUB, FNMADD, and FNMSUB are free. */
if (GET_CODE (op0) == NEG)
case FLOAT_EXTEND:
if (speed)
- *cost += extra_cost->fp[mode == DFmode].widen;
+ {
+ if (VECTOR_MODE_P (mode))
+ {
+ /*Vector truncate. */
+ *cost += extra_cost->vect.alu;
+ }
+ else
+ *cost += extra_cost->fp[mode == DFmode].widen;
+ }
return false;
case FLOAT_TRUNCATE:
if (speed)
- *cost += extra_cost->fp[mode == DFmode].narrow;
+ {
+ if (VECTOR_MODE_P (mode))
+ {
+ /*Vector conversion. */
+ *cost += extra_cost->vect.alu;
+ }
+ else
+ *cost += extra_cost->fp[mode == DFmode].narrow;
+ }
return false;
case FIX:
}
if (speed)
- *cost += extra_cost->fp[GET_MODE (x) == DFmode].toint;
-
+ {
+ if (VECTOR_MODE_P (mode))
+ *cost += extra_cost->vect.alu;
+ else
+ *cost += extra_cost->fp[GET_MODE (x) == DFmode].toint;
+ }
*cost += rtx_cost (x, (enum rtx_code) code, 0, speed);
return true;
case ABS:
- if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+ if (VECTOR_MODE_P (mode))
+ {
+ /* ABS (vector). */
+ if (speed)
+ *cost += extra_cost->vect.alu;
+ }
+ else if (GET_MODE_CLASS (mode) == MODE_FLOAT)
{
op0 = XEXP (x, 0);
case SMIN:
if (speed)
{
- /* FMAXNM/FMINNM/FMAX/FMIN.
- TODO: This may not be accurate for all implementations, but
- we do not model this in the cost tables. */
- *cost += extra_cost->fp[mode == DFmode].addsub;
+ if (VECTOR_MODE_P (mode))
+ *cost += extra_cost->vect.alu;
+ else
+ {
+ /* FMAXNM/FMINNM/FMAX/FMIN.
+ TODO: This may not be accurate for all implementations, but
+ we do not model this in the cost tables. */
+ *cost += extra_cost->fp[mode == DFmode].addsub;
+ }
}
return false;
2, /* stm_regs_per_insn_subsequent. */
COSTS_N_INSNS (1), /* storef. */
COSTS_N_INSNS (1), /* stored. */
- COSTS_N_INSNS (1) /* store_unaligned. */
+ COSTS_N_INSNS (1), /* store_unaligned. */
+ COSTS_N_INSNS (1), /* loadv. */
+ COSTS_N_INSNS (1) /* storev. */
},
{
/* FP SFmode */
2, /* stm_regs_per_insn_subsequent. */
COSTS_N_INSNS (1), /* storef. */
COSTS_N_INSNS (1), /* stored. */
- COSTS_N_INSNS (1) /* store_unaligned. */
+ COSTS_N_INSNS (1), /* store_unaligned. */
+ COSTS_N_INSNS (1), /* loadv. */
+ COSTS_N_INSNS (1) /* storev. */
},
{
/* FP SFmode */
2, /* stm_regs_per_insn_subsequent. */
COSTS_N_INSNS (2), /* storef. */
COSTS_N_INSNS (2), /* stored. */
- COSTS_N_INSNS (1) /* store_unaligned. */
+ COSTS_N_INSNS (1), /* store_unaligned. */
+ COSTS_N_INSNS (1), /* loadv. */
+ COSTS_N_INSNS (1) /* storev. */
},
{
/* FP SFmode */
2, /* stm_regs_per_insn_subsequent. */
COSTS_N_INSNS (2), /* storef. */
COSTS_N_INSNS (2), /* stored. */
- COSTS_N_INSNS (1) /* store_unaligned. */
+ COSTS_N_INSNS (1), /* store_unaligned. */
+ COSTS_N_INSNS (1), /* loadv. */
+ COSTS_N_INSNS (1) /* storev. */
},
{
/* FP SFmode */
2, /* stm_regs_per_insn_subsequent. */
COSTS_N_INSNS (2), /* storef. */
COSTS_N_INSNS (2), /* stored. */
- 0 /* store_unaligned. */
+ 0, /* store_unaligned. */
+ COSTS_N_INSNS (1), /* loadv. */
+ COSTS_N_INSNS (1) /* storev. */
},
{
/* FP SFmode */
2, /* stm_regs_per_insn_subsequent. */
0, /* storef. */
0, /* stored. */
- 0 /* store_unaligned. */
+ 0, /* store_unaligned. */
+ COSTS_N_INSNS (1), /* loadv. */
+ COSTS_N_INSNS (1) /* storev. */
},
{
/* FP SFmode */
1, /* stm_regs_per_insn_subsequent. */
COSTS_N_INSNS (2), /* storef. */
COSTS_N_INSNS (3), /* stored. */
- COSTS_N_INSNS (1) /* store_unaligned. */
+ COSTS_N_INSNS (1), /* store_unaligned. */
+ COSTS_N_INSNS (1), /* loadv. */
+ COSTS_N_INSNS (1) /* storev. */
},
{
/* FP SFmode */