@@ -252,7 +252,8 @@ (define_constraint "P"
(and (match_code "const_int")
(match_test "((- (unsigned HOST_WIDE_INT) ival) + 0x8000) < 0x10000")))
-;; Floating-point constraints
+;; Floating-point constraints. These two are defined so that insn
+;; length attributes can be calculated exactly.
(define_constraint "G"
"Constant that can be copied into GPR with two insns for DF/DI
@@ -36,7 +36,6 @@ extern int vspltis_shifted (rtx);
extern HOST_WIDE_INT const_vector_elt_as_int (rtx, unsigned int);
extern bool macho_lo_sum_memory_operand (rtx, machine_mode);
extern int num_insns_constant (rtx, machine_mode);
-extern int num_insns_constant_wide (HOST_WIDE_INT);
extern int small_data_operand (rtx, machine_mode);
extern bool mem_operand_gpr (rtx, machine_mode);
extern bool mem_operand_ds_form (rtx, machine_mode);
@@ -5818,7 +5818,7 @@ direct_return (void)
/* Return the number of instructions it takes to form a constant in an
integer register. */
-int
+static int
num_insns_constant_wide (HOST_WIDE_INT value)
{
/* signed constant loadable with addi */
@@ -5856,16 +5856,13 @@ num_insns_constant_wide (HOST_WIDE_INT value)
int
num_insns_constant (rtx op, machine_mode mode)
{
- HOST_WIDE_INT low, high;
+ HOST_WIDE_INT val;
switch (GET_CODE (op))
{
case CONST_INT:
- if ((INTVAL (op) >> 31) != 0 && (INTVAL (op) >> 31) != -1
- && rs6000_is_valid_and_mask (op, mode))
- return 2;
- else
- return num_insns_constant_wide (INTVAL (op));
+ val = INTVAL (op);
+ break;
case CONST_WIDE_INT:
{
@@ -5876,50 +5873,62 @@ num_insns_constant (rtx op, machine_mode mode)
return ins;
}
- case CONST_DOUBLE:
+ case CONST_DOUBLE:
+ {
+ const struct real_value *rv = CONST_DOUBLE_REAL_VALUE (op);
+
if (mode == SFmode || mode == SDmode)
{
long l;
- if (DECIMAL_FLOAT_MODE_P (mode))
- REAL_VALUE_TO_TARGET_DECIMAL32
- (*CONST_DOUBLE_REAL_VALUE (op), l);
+ if (mode == SDmode)
+ REAL_VALUE_TO_TARGET_DECIMAL32 (*rv, l);
else
- REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (op), l);
- return num_insns_constant_wide ((HOST_WIDE_INT) l);
+ REAL_VALUE_TO_TARGET_SINGLE (*rv, l);
+ /* See the first define_split in rs6000.md handling a
+ const_double_operand. */
+ val = l;
+ mode = SImode;
}
-
- long l[2];
- if (DECIMAL_FLOAT_MODE_P (mode))
- REAL_VALUE_TO_TARGET_DECIMAL64 (*CONST_DOUBLE_REAL_VALUE (op), l);
- else
- REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (op), l);
- high = l[WORDS_BIG_ENDIAN == 0];
- low = l[WORDS_BIG_ENDIAN != 0];
-
- if (TARGET_32BIT)
- return (num_insns_constant_wide (low)
- + num_insns_constant_wide (high));
- else
+ else if (mode == DFmode || mode == DDmode)
{
- if ((high == 0 && low >= 0)
- || (high == -1 && low < 0))
- return num_insns_constant_wide (low);
-
- else if (rs6000_is_valid_and_mask (op, mode))
- return 2;
-
- else if (low == 0)
- return num_insns_constant_wide (high) + 1;
+ long l[2];
+ if (mode == DDmode)
+ REAL_VALUE_TO_TARGET_DECIMAL64 (*rv, l);
else
- return (num_insns_constant_wide (high)
- + num_insns_constant_wide (low) + 1);
+ REAL_VALUE_TO_TARGET_DOUBLE (*rv, l);
+
+ HOST_WIDE_INT high = l[WORDS_BIG_ENDIAN == 0];
+ HOST_WIDE_INT low = l[WORDS_BIG_ENDIAN != 0];
+
+ if (TARGET_32BIT)
+ /* We'll be loading the double into two registers.
+ See the second define_split in rs6000.md handling a
+ const_double_operand. */
+ return (num_insns_constant_wide (low)
+ + num_insns_constant_wide (high));
+
+ /* See the third define_split in rs6000.md handling a
+ const_double_operand. */
+ val = (low & 0xffffffffUL) | (high << 32);
+ mode = DImode;
}
+ else
+ gcc_unreachable ();
+ op = NULL_RTX;
+ }
+ break;
default:
gcc_unreachable ();
}
+
+ int ins = num_insns_constant_wide (val);
+ if (ins > 2
+ && rs6000_is_valid_and_mask (op ? op : GEN_INT (val), mode))
+ ins = 2;
+ return ins;
}
/* Interpret element ELT of the CONST_VECTOR OP as an integer value.
@@ -7713,7 +7713,7 @@ (define_insn_and_split "*mov<mode>_32bit"
(define_insn_and_split "*mov<mode>_softfloat"
[(set (match_operand:FMOVE128 0 "nonimmediate_operand" "=Y,r,r")
- (match_operand:FMOVE128 1 "input_operand" "r,YGHF,r"))]
+ (match_operand:FMOVE128 1 "input_operand" "r,Y,r"))]
"TARGET_SOFT_FLOAT
&& (gpc_reg_operand (operands[0], <MODE>mode)
|| gpc_reg_operand (operands[1], <MODE>mode))"
@@ -8670,7 +8670,7 @@ (define_insn "*movdi_internal32"
(match_operand:DI 1 "input_operand"
"r, Y, r, ^d, m, ^d,
- IJKnGHF, ^wb, $wv, wY, Z, ^wi,
+ IJKnF, ^wb, $wv, wY, Z, ^wi,
Oj, wM, OjwM, Oj, wM, wS,
wB"))]