Commit 4e74d8ec by Michael Meissner

Make long longs use normal CONST_DOUBLE in movdi, do not split too early

From-SVN: r11513
parent 9740123d
...@@ -524,6 +524,90 @@ reg_or_cint_operand (op, mode) ...@@ -524,6 +524,90 @@ reg_or_cint_operand (op, mode)
return GET_CODE (op) == CONST_INT || gpc_reg_operand (op, mode); return GET_CODE (op) == CONST_INT || gpc_reg_operand (op, mode);
} }
/* Return the number of instructions it takes to form a constant in an
integer register. */
static int
num_insns_constant_wide (value)
HOST_WIDE_INT value;
{
/* signed constant loadable with {cal|addi} */
if (((unsigned HOST_WIDE_INT)value + 0x8000) < 0x10000)
return 1;
#if HOST_BITS_PER_WIDE_INT == 32
/* constant loadable with {cau|addis} */
else if ((value & 0xffff) == 0)
return 1;
#else
/* constant loadable with {cau|addis} */
else if ((value & 0xffff) == 0 && (value & ~0xffffffff) == 0)
return 1;
else if (TARGET_64BIT)
{
HOST_WIDE_INT low = value & 0xffffffff;
HOST_WIDE_INT high = value >> 32;
if (high == 0 && (low & 0x80000000) == 0)
return 2;
else if (high == 0xffffffff && (low & 0x80000000) != 0)
return 2;
else if (!low)
return num_insns_constant_wide (high) + 1;
else
return (num_insns_constant_wide (high)
+ num_insns_constant_low (low) + 1);
}
#endif
else
return 2;
}
int
num_insns_constant (op, mode)
rtx op;
enum machine_mode mode;
{
if (mode != SImode && mode != DImode)
abort ();
if (GET_CODE (op) == CONST_INT)
return num_insns_constant_wide (INTVAL (op));
else if (GET_CODE (op) == CONST_DOUBLE && TARGET_32BIT)
return (num_insns_constant_wide (CONST_DOUBLE_LOW (op))
+ num_insns_constant_wide (CONST_DOUBLE_HIGH (op)));
else if (GET_CODE (op) == CONST_DOUBLE && TARGET_64BIT)
{
HOST_WIDE_INT low = CONST_DOUBLE_LOW (op);
HOST_WIDE_INT high = CONST_DOUBLE_HIGH (op);
if (high == 0 && (low & 0x80000000) == 0)
return num_insns_constant_wide (low);
else if (((high & 0xffffffff) == 0xffffffff)
&& ((low & 0x80000000) != 0))
return num_insns_constant_wide (low);
else if (low == 0)
return num_insns_constant_wide (high) + 1;
else
return (num_insns_constant_wide (high)
+ num_insns_constant_wide (low) + 1);
}
else
abort ();
}
/* Return 1 if the operand is a CONST_DOUBLE and it can be put into a register /* Return 1 if the operand is a CONST_DOUBLE and it can be put into a register
with one instruction per word. We only do this if we can safely read with one instruction per word. We only do this if we can safely read
CONST_DOUBLE_{LOW,HIGH}. */ CONST_DOUBLE_{LOW,HIGH}. */
...@@ -535,11 +619,11 @@ easy_fp_constant (op, mode) ...@@ -535,11 +619,11 @@ easy_fp_constant (op, mode)
{ {
if (GET_CODE (op) != CONST_DOUBLE if (GET_CODE (op) != CONST_DOUBLE
|| GET_MODE (op) != mode || GET_MODE (op) != mode
|| GET_MODE_CLASS (mode) != MODE_FLOAT) || (GET_MODE_CLASS (mode) != MODE_FLOAT && mode != DImode))
return 0; return 0;
/* Consider all constants with -msoft-float to be easy */ /* Consider all constants with -msoft-float to be easy */
if (TARGET_SOFT_FLOAT) if (TARGET_SOFT_FLOAT && mode != DImode)
return 1; return 1;
if (mode == DFmode) if (mode == DFmode)
...@@ -550,10 +634,11 @@ easy_fp_constant (op, mode) ...@@ -550,10 +634,11 @@ easy_fp_constant (op, mode)
REAL_VALUE_FROM_CONST_DOUBLE (rv, op); REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
REAL_VALUE_TO_TARGET_DOUBLE (rv, k); REAL_VALUE_TO_TARGET_DOUBLE (rv, k);
return (((unsigned) (k[0] + 0x8000) < 0x10000 || (k[0] & 0xffff) == 0) return (num_insns_constant_wide ((HOST_WIDE_INT)k[0]) == 1
&& ((unsigned) (k[1] + 0x8000) < 0x10000 || (k[1] & 0xffff) == 0)); && num_insns_constant_wide ((HOST_WIDE_INT)k[1]) == 1);
} }
else
else if (mode == SFmode)
{ {
long l; long l;
REAL_VALUE_TYPE rv; REAL_VALUE_TYPE rv;
...@@ -561,8 +646,14 @@ easy_fp_constant (op, mode) ...@@ -561,8 +646,14 @@ easy_fp_constant (op, mode)
REAL_VALUE_FROM_CONST_DOUBLE (rv, op); REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
REAL_VALUE_TO_TARGET_SINGLE (rv, l); REAL_VALUE_TO_TARGET_SINGLE (rv, l);
return ((unsigned) (l + 0x8000) < 0x10000 || (l & 0xffff) == 0); return num_insns_constant_wide (l) == 1;
} }
else if (mode == DImode && TARGET_32BIT)
return num_insns_constant (op, DImode) == 2;
else
abort ();
} }
/* Return 1 if the operand is in volatile memory. Note that during the /* Return 1 if the operand is in volatile memory. Note that during the
...@@ -821,6 +912,11 @@ input_operand (op, mode) ...@@ -821,6 +912,11 @@ input_operand (op, mode)
&& easy_fp_constant (op, mode)) && easy_fp_constant (op, mode))
return 1; return 1;
/* Allow any integer constant. */
if (GET_MODE_CLASS (mode) == MODE_INT
&& (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE))
return 1;
/* For floating-point or multi-word mode, the only remaining valid type /* For floating-point or multi-word mode, the only remaining valid type
is a register. */ is a register. */
if (GET_MODE_CLASS (mode) == MODE_FLOAT if (GET_MODE_CLASS (mode) == MODE_FLOAT
...@@ -833,10 +929,6 @@ input_operand (op, mode) ...@@ -833,10 +929,6 @@ input_operand (op, mode)
if (register_operand (op, mode)) if (register_operand (op, mode))
return 1; return 1;
/* For integer modes, any constant is ok. */
if (GET_CODE (op) == CONST_INT)
return 1;
/* A SYMBOL_REF referring to the TOC is valid. */ /* A SYMBOL_REF referring to the TOC is valid. */
if (LEGITIMATE_CONSTANT_POOL_ADDRESS_P (op)) if (LEGITIMATE_CONSTANT_POOL_ADDRESS_P (op))
return 1; return 1;
......
...@@ -995,10 +995,14 @@ enum reg_class ...@@ -995,10 +995,14 @@ enum reg_class
Here VALUE is the CONST_DOUBLE rtx itself. Here VALUE is the CONST_DOUBLE rtx itself.
We flag for special constants when we can copy the constant into We flag for special constants when we can copy the constant into
a general register in two insns for DF and one insn for SF. */ a general register in two insns for DF/DI and one insn for SF.
#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ 'H' is used for DI constants that take 3 insns. */
((C) == 'G' ? easy_fp_constant (VALUE, GET_MODE (VALUE)) : 0)
#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
((C) == 'G' ? easy_fp_constant (VALUE, GET_MODE (VALUE)) : \
(C) == 'H' ? (num_insns_constant (VALUE, DImode) == 3) : \
0)
/* Optional extra constraints for this machine. /* Optional extra constraints for this machine.
...@@ -2819,6 +2823,7 @@ extern int reg_or_short_operand (); ...@@ -2819,6 +2823,7 @@ extern int reg_or_short_operand ();
extern int reg_or_neg_short_operand (); extern int reg_or_neg_short_operand ();
extern int reg_or_u_short_operand (); extern int reg_or_u_short_operand ();
extern int reg_or_cint_operand (); extern int reg_or_cint_operand ();
extern int num_insns_constant ();
extern int easy_fp_constant (); extern int easy_fp_constant ();
extern int volatile_mem_operand (); extern int volatile_mem_operand ();
extern int offsettable_addr_operand (); extern int offsettable_addr_operand ();
......
...@@ -5429,8 +5429,9 @@ ...@@ -5429,8 +5429,9 @@
if (GET_CODE (operands[0]) != REG) if (GET_CODE (operands[0]) != REG)
operands[1] = force_reg (DImode, operands[1]); operands[1] = force_reg (DImode, operands[1]);
if (GET_CODE (operands[1]) == CONST_DOUBLE if (TARGET_64BIT
|| GET_CODE (operands[1]) == CONST_INT) && (GET_CODE (operands[1]) == CONST_DOUBLE
|| GET_CODE (operands[1]) == CONST_INT))
{ {
HOST_WIDE_INT low; HOST_WIDE_INT low;
HOST_WIDE_INT high; HOST_WIDE_INT high;
...@@ -5453,39 +5454,23 @@ ...@@ -5453,39 +5454,23 @@
} }
#endif #endif
if (! TARGET_POWERPC64) if (high)
{ {
emit_move_insn (gen_rtx (SUBREG, SImode, operands[0], emit_move_insn (operands[0], GEN_INT (high));
WORDS_BIG_ENDIAN), GEN_INT (low)); emit_insn (gen_ashldi3 (operands[0], operands[0], GEN_INT(32)));
if (low)
emit_move_insn (gen_rtx (SUBREG, SImode, operands[0], {
! WORDS_BIG_ENDIAN), GEN_INT (high)); HOST_WIDE_INT low_low = low & 0xffff;
DONE; HOST_WIDE_INT low_high = low & (~ (HOST_WIDE_INT) 0xffff);
} if (low_high)
else emit_insn (gen_iordi3 (operands[0], operands[0],
{ GEN_INT (low_high)));
if (high + 0x8000 >= 0x10000) if (low_low)
{ emit_insn (gen_iordi3 (operands[0], operands[0],
emit_move_insn (gen_rtx (SUBREG, SImode, operands[0], 1), GEN_INT (low_low)));
GEN_INT (high)); }
emit_insn (gen_ashldi3 (operands[0], operands[0], GEN_INT(32))); DONE;
if (low) }
{
HOST_WIDE_INT low_low = low & 0xffff;
HOST_WIDE_INT low_high = low & (~ (HOST_WIDE_INT) 0xffff);
if (low_high)
emit_insn (gen_iordi3 (operands[0], operands[0],
GEN_INT (low_high)));
if (low_low)
emit_insn (gen_iordi3 (operands[0], operands[0],
GEN_INT (low_low)));
}
}
else if (low)
emit_move_insn (gen_rtx (SUBREG, SImode, operands[0], 1),
GEN_INT (low));
DONE;
}
} }
/* Stores between FPR and any non-FPR registers must go through a /* Stores between FPR and any non-FPR registers must go through a
...@@ -5506,10 +5491,11 @@ ...@@ -5506,10 +5491,11 @@
}") }")
(define_insn "" (define_insn ""
[(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,f,f,m") [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,f,f,m,r,r,r,r,r")
(match_operand:DI 1 "input_operand" "r,m,r,f,m,f"))] (match_operand:DI 1 "input_operand" "r,m,r,f,m,f,IJK,n,G,H,F"))]
"! TARGET_POWERPC64 && (gpc_reg_operand (operands[0], DImode) "TARGET_32BIT
|| gpc_reg_operand (operands[1], DImode))" && (gpc_reg_operand (operands[0], DImode)
|| gpc_reg_operand (operands[1], DImode))"
"* "*
{ {
switch (which_alternative) switch (which_alternative)
...@@ -5540,16 +5526,121 @@ ...@@ -5540,16 +5526,121 @@
return \"lfd%U1%X1 %0,%1\"; return \"lfd%U1%X1 %0,%1\";
case 5: case 5:
return \"stfd%U0%X0 %1,%0\"; return \"stfd%U0%X0 %1,%0\";
case 6:
case 7:
case 8:
case 9:
case 10:
return \"#\";
} }
}" }"
[(set_attr "type" "*,load,store,fp,fpload,fpstore") [(set_attr "type" "*,load,store,fp,fpload,fpstore,*,*,*,*,*")
(set_attr "length" "8,8,8,*,*,*")]) (set_attr "length" "8,8,8,*,*,*,8,12,8,12,16")])
(define_split
[(set (match_operand:DI 0 "gpc_reg_operand" "")
(match_operand:DI 1 "const_int_operand" ""))]
"TARGET_32BIT && reload_completed && num_insns_constant (operands[1], DImode) <= 1"
[(set (match_dup 2) (match_dup 4))
(set (match_dup 3) (match_dup 1))]
"
{
operands[2] = gen_rtx (SUBREG, SImode, operands[0], WORDS_BIG_ENDIAN == 0);
operands[3] = gen_rtx (SUBREG, SImode, operands[0], WORDS_BIG_ENDIAN != 0);
operands[4] = (INTVAL (operands[1]) & 0x80000000) ? constm1_rtx : const0_rtx;
}")
(define_split
[(set (match_operand:DI 0 "gpc_reg_operand" "")
(match_operand:DI 1 "const_int_operand" ""))]
"TARGET_32BIT && reload_completed && num_insns_constant (operands[1], DImode) >= 2"
[(set (match_dup 3) (match_dup 5))
(set (match_dup 2) (match_dup 4))
(set (match_dup 3) (ior:SI (match_dup 3) (match_dup 6)))]
"
{
HOST_WIDE_INT value = INTVAL (operands[1]);
operands[2] = gen_rtx (SUBREG, SImode, operands[0], WORDS_BIG_ENDIAN == 0);
operands[3] = gen_rtx (SUBREG, SImode, operands[0], WORDS_BIG_ENDIAN != 0);
operands[4] = (value & 0x80000000) ? constm1_rtx : const0_rtx;
operands[5] = GEN_INT (value & 0xffff0000);
operands[6] = GEN_INT (value & 0x0000ffff);
}")
(define_split
[(set (match_operand:DI 0 "gpc_reg_operand" "")
(match_operand:DI 1 "const_double_operand" ""))]
"TARGET_32BIT && reload_completed && num_insns_constant (operands[1], DImode) <= 2"
[(set (match_dup 2) (match_dup 4))
(set (match_dup 3) (match_dup 5))]
"
{
operands[2] = gen_rtx (SUBREG, SImode, operands[0], WORDS_BIG_ENDIAN == 0);
operands[3] = gen_rtx (SUBREG, SImode, operands[0], WORDS_BIG_ENDIAN != 0);
operands[4] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
operands[5] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
}")
(define_split
[(set (match_operand:DI 0 "gpc_reg_operand" "")
(match_operand:DI 1 "const_double_operand" ""))]
"TARGET_32BIT && reload_completed && num_insns_constant (operands[1], DImode) == 3"
[(set (match_dup 2) (match_dup 4))
(set (match_dup 3) (match_dup 5))
(set (match_dup 2) (ior:SI (match_dup 2) (match_dup 6)))]
"
{
HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]);
rtx high_reg = gen_rtx (SUBREG, SImode, operands[0], WORDS_BIG_ENDIAN == 0);
rtx low_reg = gen_rtx (SUBREG, SImode, operands[0], WORDS_BIG_ENDIAN != 0);
if (((unsigned HOST_WIDE_INT) (low + 0x8000) < 0x10000)
|| (low & 0xffff) == 0)
{
operands[2] = high_reg;
operands[3] = low_reg;
operands[4] = GEN_INT (high & 0xffff0000);
operands[5] = GEN_INT (low);
operands[6] = GEN_INT (high & 0x0000ffff);
}
else
{
operands[2] = low_reg;
operands[3] = high_reg;
operands[4] = GEN_INT (low & 0xffff0000);
operands[5] = GEN_INT (high);
operands[6] = GEN_INT (low & 0x0000ffff);
}
}")
(define_split
[(set (match_operand:DI 0 "gpc_reg_operand" "")
(match_operand:DI 1 "const_double_operand" ""))]
"TARGET_32BIT && reload_completed && num_insns_constant (operands[1], DImode) >= 4"
[(set (match_dup 2) (match_dup 4))
(set (match_dup 3) (match_dup 5))
(set (match_dup 2) (ior:SI (match_dup 2) (match_dup 6)))
(set (match_dup 3) (ior:SI (match_dup 3) (match_dup 7)))]
"
{
HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]);
operands[2] = gen_rtx (SUBREG, SImode, operands[0], WORDS_BIG_ENDIAN == 0);
operands[3] = gen_rtx (SUBREG, SImode, operands[0], WORDS_BIG_ENDIAN != 0);
operands[4] = GEN_INT (high & 0xffff0000);
operands[5] = GEN_INT (low & 0xffff0000);
operands[6] = GEN_INT (high & 0x0000ffff);
operands[7] = GEN_INT (low & 0x0000ffff);
}")
(define_insn "" (define_insn ""
[(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,f,f,m,r,*h,*h") [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,f,f,m,r,*h,*h")
(match_operand:DI 1 "input_operand" "r,m,r,I,J,n,R,f,m,f,*h,r,0"))] (match_operand:DI 1 "input_operand" "r,m,r,I,J,nF,R,f,m,f,*h,r,0"))]
"TARGET_POWERPC64 && (gpc_reg_operand (operands[0], DImode) "TARGET_64BIT
|| gpc_reg_operand (operands[1], DImode))" && (gpc_reg_operand (operands[0], DImode)
|| gpc_reg_operand (operands[1], DImode))"
"@ "@
mr %0,%1 mr %0,%1
ld%U1%X1 %0,%1 ld%U1%X1 %0,%1
...@@ -5574,7 +5665,7 @@ ...@@ -5574,7 +5665,7 @@
(define_split (define_split
[(set (match_operand:DI 0 "gpc_reg_operand" "") [(set (match_operand:DI 0 "gpc_reg_operand" "")
(match_operand:DI 1 "const_double_operand" ""))] (match_operand:DI 1 "const_double_operand" ""))]
"TARGET_POWERPC64" "TARGET_64BIT && num_insns_constant (operands[1], DImode) > 1"
[(set (match_dup 0) [(set (match_dup 0)
(match_dup 2)) (match_dup 2))
(set (match_dup 0) (set (match_dup 0)
......
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