/* On the RS/6000, if it is valid in the insn, it is free.
So this always returns 0. */
case CONST_INT:
+ if (((outer_code == SET
+ || outer_code == PLUS
+ || outer_code == MINUS)
+ && (CONST_OK_FOR_LETTER_P (INTVAL (x), 'I')
+ || CONST_OK_FOR_LETTER_P (INTVAL (x), 'L')))
+ || ((outer_code == IOR || outer_code == XOR)
+ && (CONST_OK_FOR_LETTER_P (INTVAL (x), 'K')
+ || CONST_OK_FOR_LETTER_P (INTVAL (x), 'L')))
+ || (outer_code == AND
+ && (CONST_OK_FOR_LETTER_P (INTVAL (x), 'K')
+ || CONST_OK_FOR_LETTER_P (INTVAL (x), 'L')
+ || CONST_OK_FOR_LETTER_P (INTVAL (x), 'T')))
+ || outer_code == ASHIFT
+ || outer_code == ASHIFTRT
+ || outer_code == LSHIFTRT
+ || outer_code == ROTATE
+ || outer_code == ROTATERT
+ || (outer_code == MULT
+ && CONST_OK_FOR_LETTER_P (INTVAL (x), 'I'))
+ || (outer_code == COMPARE
+ && (CONST_OK_FOR_LETTER_P (INTVAL (x), 'I')
+ || CONST_OK_FOR_LETTER_P (INTVAL (x), 'K'))))
+ {
+ *total = 0;
+ return true;
+ }
+ else if ((outer_code == PLUS
+ && reg_or_add_cint64_operand (x, VOIDmode))
+ || (outer_code == MINUS
+ && reg_or_sub_cint64_operand (x, VOIDmode))
+ || ((outer_code == SET
+ || outer_code == IOR
+ || outer_code == XOR)
+ && (INTVAL (x)
+ & ~ (unsigned HOST_WIDE_INT) 0xffffffff) == 0))
+ {
+ *total = COSTS_N_INSNS (1);
+ return true;
+ }
+ /* FALLTHRU */
+
+ case CONST_DOUBLE:
+ if (mode == DImode
+ && ((outer_code == AND
+ && (CONST_OK_FOR_LETTER_P (INTVAL (x), 'K')
+ || CONST_OK_FOR_LETTER_P (INTVAL (x), 'L')
+ || CONST_OK_FOR_LETTER_P (INTVAL (x), 'S')))
+ || ((outer_code == IOR || outer_code == XOR)
+ && CONST_DOUBLE_HIGH (x) == 0
+ && (CONST_DOUBLE_LOW (x)
+ & ~ (unsigned HOST_WIDE_INT) 0xffff) == 0)))
+ {
+ *total = 0;
+ return true;
+ }
+ else if (mode == DImode
+ && (outer_code == SET
+ || outer_code == IOR
+ || outer_code == XOR)
+ && CONST_DOUBLE_HIGH (x) == 0)
+ {
+ *total = COSTS_N_INSNS (1);
+ return true;
+ }
+ /* FALLTHRU */
+
case CONST:
+ case HIGH:
case LABEL_REF:
case SYMBOL_REF:
- case CONST_DOUBLE:
- case HIGH:
- *total = 0;
+ case MEM:
+ /* When optimizing for size, MEM should be slightly more expensive
+ than generating address, e.g., (plus (reg) (const)).
+ L1 cache latecy is about two instructions. */
+ *total = optimize_size ? COSTS_N_INSNS (1) + 1 : COSTS_N_INSNS (2);
return true;
case PLUS:
if (mode == DFmode)
- *total = GET_CODE (XEXP (x, 0)) == MULT
- ? rs6000_cost->dmul
- : rs6000_cost->fp;
+ {
+ if (GET_CODE (XEXP (x, 0)) == MULT)
+ {
+ /* FNMA accounted in outer NEG. */
+ if (outer_code == NEG)
+ *total = rs6000_cost->dmul - rs6000_cost->fp;
+ else
+ *total = rs6000_cost->dmul;
+ }
+ else
+ *total = rs6000_cost->fp;
+ }
else if (mode == SFmode)
- *total = rs6000_cost->fp;
+ {
+ /* FNMA accounted in outer NEG. */
+ if (outer_code == NEG && GET_CODE (XEXP (x, 0)) == MULT)
+ *total = 0;
+ else
+ *total = rs6000_cost->fp;
+ }
else if (GET_CODE (XEXP (x, 0)) == MULT)
{
/* The rs6000 doesn't have shift-and-add instructions. */
*total += COSTS_N_INSNS (1);
}
else
- *total = ((GET_CODE (XEXP (x, 1)) == CONST_INT
- && ((unsigned HOST_WIDE_INT) (INTVAL (XEXP (x, 1))
- + 0x8000) >= 0x10000)
- && ((INTVAL (XEXP (x, 1)) & 0xffff) != 0))
- ? COSTS_N_INSNS (2)
- : COSTS_N_INSNS (1));
- return true;
+ *total = COSTS_N_INSNS (1);
+ return false;
case MINUS:
if (mode == DFmode)
- *total = GET_CODE (XEXP (x, 0)) == MULT
- ? rs6000_cost->dmul
- : rs6000_cost->fp;
+ {
+ if (GET_CODE (XEXP (x, 0)) == MULT)
+ {
+ /* FNMA accounted in outer NEG. */
+ if (outer_code == NEG)
+ *total = 0;
+ else
+ *total = rs6000_cost->dmul;
+ }
+ else
+ *total = rs6000_cost->fp;
+ }
else if (mode == SFmode)
- *total = rs6000_cost->fp;
+ {
+ /* FNMA accounted in outer NEG. */
+ if (outer_code == NEG && GET_CODE (XEXP (x, 0)) == MULT)
+ *total = 0;
+ else
+ *total = rs6000_cost->fp;
+ }
else if (GET_CODE (XEXP (x, 0)) == MULT)
{
/* The rs6000 doesn't have shift-and-sub instructions. */
}
else
*total = COSTS_N_INSNS (1);
- return true;
-
- case AND:
- case IOR:
- case XOR:
- *total = ((GET_CODE (XEXP (x, 1)) == CONST_INT
- && (INTVAL (XEXP (x, 1)) & (~ (HOST_WIDE_INT) 0xffff)) != 0
- && ((INTVAL (XEXP (x, 1)) & 0xffff) != 0))
- ? COSTS_N_INSNS (2)
- : COSTS_N_INSNS (1));
- return true;
+ return false;
case MULT:
if (GET_CODE (XEXP (x, 1)) == CONST_INT)
else
*total = rs6000_cost->mulsi_const;
}
+ /* FMA accounted in outer PLUS/MINUS. */
+ else if ((mode == DFmode || mode == SFmode)
+ && (outer_code == PLUS || outer_code == MINUS))
+ *total = 0;
else if (mode == DFmode)
*total = rs6000_cost->dmul;
else if (mode == SFmode)
*total = rs6000_cost->muldi;
else
*total = rs6000_cost->mulsi;
- return true;
+ return false;
case DIV:
case MOD:
{
*total = mode == DFmode ? rs6000_cost->ddiv
: rs6000_cost->sdiv;
- return true;
+ return false;
}
if (GET_CODE (XEXP (x, 1)) == CONST_INT
&& exact_log2 (INTVAL (XEXP (x, 1))) >= 0)
{
*total = COSTS_N_INSNS (2);
- return true;
+ return false;
}
/* FALLTHRU */
*total = rs6000_cost->divdi;
else
*total = rs6000_cost->divsi;
- return true;
+ return false;
case FFS:
*total = COSTS_N_INSNS (4);
- return true;
-
- case NEG:
- case ABS:
- if (FLOAT_MODE_P (mode))
- *total = rs6000_cost->fp;
- else
- *total = COSTS_N_INSNS (1);
- return true;
-
- case MEM:
- /* MEM should be slightly more expensive than (plus (reg) (const)). */
- *total = COSTS_N_INSNS (1) + 1;
- return true;
+ return false;
case NOT:
+ if (outer_code == AND || outer_code == IOR || outer_code == XOR)
+ {
+ *total = 0;
+ return false;
+ }
+ /* FALLTHRU */
+
+ case AND:
+ case IOR:
+ case XOR:
+ case ASHIFT:
+ case ASHIFTRT:
+ case LSHIFTRT:
+ case ROTATE:
+ case ROTATERT:
case SIGN_EXTEND:
case ZERO_EXTEND:
- case COMPARE:
+ if (outer_code == TRUNCATE
+ && GET_CODE (XEXP (x, 0)) == MULT)
+ {
+ if (mode == DImode)
+ *total = rs6000_cost->muldi;
+ else
+ *total = rs6000_cost->mulsi;
+ return true;
+ }
*total = COSTS_N_INSNS (1);
- break;
+ return false;
+ case COMPARE:
+ case NEG:
+ case ABS:
+ if (!FLOAT_MODE_P (mode))
+ {
+ *total = COSTS_N_INSNS (1);
+ return false;
+ }
+ /* FALLTHRU */
+
+ case FLOAT:
+ case UNSIGNED_FLOAT:
+ case FIX:
+ case UNSIGNED_FIX:
+ case FLOAT_EXTEND:
case FLOAT_TRUNCATE:
*total = rs6000_cost->fp;
- return true;
+ return false;
case UNSPEC:
switch (XINT (x, 1))
*total = COSTS_N_INSNS (1);
return true;
}
+ else if (FLOAT_MODE_P (mode)
+ && TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS)
+ {
+ *total = rs6000_cost->fp;
+ return false;
+ }
+
break;
default: