rs6000.c (mask_operand): Rewrite without bit-shifting loop.

* config/rs6000/rs6000.c (mask_operand): Rewrite without
	bit-shifting loop.
	(mask64_operand): Likewise.
	(rldic_operand): Delete.
	(includes_lshift64_p): Delete.
	(includes_rldic_lshift_p): New function.
	(includes_rldicr_lshift_p): New function.
	(print_operand): Don't call rldic_operand in case 'W'.
	* config/rs6000/rs6000-protos.h (rldic_operand): Remove.
	(includes_lshift64_p): Remove.
	(includes_rldic_lshift_p): Declare.
	(includes_rldicr_lshift_p): Declare.
	* config/rs6000/rs6000.h (PREDICATE_CODES): Remove rldic_operand.
	* config/rs6000/rs6000.md <ashldi3_internal 64 bit patterns>:
	Replace match_operand rldic_operand predicate with
	const_int_operand.  Replace includes_lshift64_p condition with
	includes_rldic_lshift_p.
	<ashldi3_internal 64 bit rldicr patterns>: New.

From-SVN: r45192
This commit is contained in:
Alan Modra 2001-08-27 15:52:35 +00:00 committed by Alan Modra
parent c34cce4404
commit c50594233b
5 changed files with 323 additions and 164 deletions

View File

@ -1,3 +1,24 @@
2001-08-27 Alan Modra <amodra@bigpond.net.au>
* config/rs6000/rs6000.c (mask_operand): Rewrite without
bit-shifting loop.
(mask64_operand): Likewise.
(rldic_operand): Delete.
(includes_lshift64_p): Delete.
(includes_rldic_lshift_p): New function.
(includes_rldicr_lshift_p): New function.
(print_operand): Don't call rldic_operand in case 'W'.
* config/rs6000/rs6000-protos.h (rldic_operand): Remove.
(includes_lshift64_p): Remove.
(includes_rldic_lshift_p): Declare.
(includes_rldicr_lshift_p): Declare.
* config/rs6000/rs6000.h (PREDICATE_CODES): Remove rldic_operand.
* config/rs6000/rs6000.md <ashldi3_internal 64 bit patterns>:
Replace match_operand rldic_operand predicate with
const_int_operand. Replace includes_lshift64_p condition with
includes_rldic_lshift_p.
<ashldi3_internal 64 bit rldicr patterns>: New.
2001-08-27 Andreas Jaeger <aj@suse.de>
* emit-rtl.c: Use VA_OPEN/VA_CLOSE/VA_FIXEDARG throughout.

View File

@ -60,7 +60,6 @@ extern int non_logical_cint_operand PARAMS ((rtx, enum machine_mode));
extern int logical_operand PARAMS ((rtx, enum machine_mode));
extern int mask_operand PARAMS ((rtx, enum machine_mode));
extern int mask64_operand PARAMS ((rtx, enum machine_mode));
extern int rldic_operand PARAMS ((rtx, enum machine_mode));
extern int and64_operand PARAMS ((rtx, enum machine_mode));
extern int and_operand PARAMS ((rtx, enum machine_mode));
extern int count_register_operand PARAMS ((rtx, enum machine_mode));
@ -86,7 +85,8 @@ extern int boolean_or_operator PARAMS ((rtx, enum machine_mode));
extern int min_max_operator PARAMS ((rtx, enum machine_mode));
extern int includes_lshift_p PARAMS ((rtx, rtx));
extern int includes_rshift_p PARAMS ((rtx, rtx));
extern int includes_lshift64_p PARAMS ((rtx, rtx));
extern int includes_rldic_lshift_p PARAMS ((rtx, rtx));
extern int includes_rldicr_lshift_p PARAMS ((rtx, rtx));
extern int registers_ok_for_quad_peep PARAMS ((rtx, rtx));
extern int addrs_ok_for_quad_peep PARAMS ((rtx, rtx));
extern enum reg_class secondary_reload_class PARAMS ((enum reg_class,

View File

@ -1158,26 +1158,36 @@ mask_operand (op, mode)
register rtx op;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
HOST_WIDE_INT c;
int i;
int last_bit_value;
int transitions = 0;
unsigned HOST_WIDE_INT c, lsb;
if (GET_CODE (op) != CONST_INT)
return 0;
c = INTVAL (op);
if (c == 0 || c == ~0)
/* We don't change the number of transitions by inverting,
so make sure we start with the LS bit zero. */
if (c & 1)
c = ~c;
/* Reject all zeros or all ones. */
if (c == 0)
return 0;
last_bit_value = c & 1;
/* Find the first transition. */
lsb = c & -c;
for (i = 1; i < 32; i++)
if (((c >>= 1) & 1) != last_bit_value)
last_bit_value ^= 1, transitions++;
/* Invert to look for a second transition. */
c = ~c;
return transitions <= 2;
/* Erase first transition. */
c &= -lsb;
/* Find the second transition (if any). */
lsb = c & -c;
/* Match if all the bits above are 1's (or c is zero). */
return c == -lsb;
}
/* Return 1 if the operand is a constant that is a PowerPC64 mask.
@ -1192,133 +1202,49 @@ mask64_operand (op, mode)
{
if (GET_CODE (op) == CONST_INT)
{
HOST_WIDE_INT c = INTVAL (op);
int i;
int last_bit_value;
int transitions = 0;
unsigned HOST_WIDE_INT c, lsb;
if (c == 0 || c == ~0)
/* We don't change the number of transitions by inverting,
so make sure we start with the LS bit zero. */
c = INTVAL (op);
if (c & 1)
c = ~c;
/* Reject all zeros or all ones. */
if (c == 0)
return 0;
last_bit_value = c & 1;
for (i = 1; i < HOST_BITS_PER_WIDE_INT; i++)
if (((c >>= 1) & 1) != last_bit_value)
last_bit_value ^= 1, transitions++;
return transitions <= 1;
/* Find the transition, and check that all bits above are 1's. */
lsb = c & -c;
return c == -lsb;
}
else if (GET_CODE (op) == CONST_DOUBLE
&& (mode == VOIDmode || mode == DImode))
{
HOST_WIDE_INT low = CONST_DOUBLE_LOW (op);
#if HOST_BITS_PER_WIDE_INT == 32
HOST_WIDE_INT high = CONST_DOUBLE_HIGH (op);
#endif
int i;
int last_bit_value;
int transitions = 0;
unsigned HOST_WIDE_INT low, high, lsb;
if ((low == 0
#if HOST_BITS_PER_WIDE_INT == 32
&& high == 0
#endif
)
|| (low == ~0
#if HOST_BITS_PER_WIDE_INT == 32
&& high == ~0
#endif
))
return 0;
if (HOST_BITS_PER_WIDE_INT < 64)
high = CONST_DOUBLE_HIGH (op);
last_bit_value = low & 1;
low = CONST_DOUBLE_LOW (op);
if (low & 1)
{
if (HOST_BITS_PER_WIDE_INT < 64)
high = ~high;
low = ~low;
}
for (i = 1; i < HOST_BITS_PER_WIDE_INT; i++)
if (((low >>= 1) & 1) != last_bit_value)
last_bit_value ^= 1, transitions++;
if (low == 0)
{
if (HOST_BITS_PER_WIDE_INT >= 64 || high == 0)
return 0;
#if HOST_BITS_PER_WIDE_INT == 32
if ((high & 1) != last_bit_value)
last_bit_value ^= 1, transitions++;
lsb = high & -high;
return high == -lsb;
}
for (i = 1; i < HOST_BITS_PER_WIDE_INT; i++)
if (((high >>= 1) & 1) != last_bit_value)
last_bit_value ^= 1, transitions++;
#endif
return transitions <= 1;
}
else
return 0;
}
/* Return 1 if the operand is a constant that is a PowerPC64 mask.
It is if there are no more than two 1->0 or 0->1 transitions.
Reject all ones and all zeros, since these should have been optimized
away and confuse the making of MB and ME. */
int
rldic_operand (op, mode)
register rtx op;
enum machine_mode mode;
{
if (GET_CODE (op) == CONST_INT)
{
HOST_WIDE_INT c = INTVAL (op);
int i;
int last_bit_value;
int transitions = 0;
if (c == 0 || c == ~0)
return 0;
last_bit_value = c & 1;
for (i = 1; i < HOST_BITS_PER_WIDE_INT; i++)
if (((c >>= 1) & 1) != last_bit_value)
last_bit_value ^= 1, transitions++;
return transitions <= 2;
}
else if (GET_CODE (op) == CONST_DOUBLE
&& (mode == VOIDmode || mode == DImode))
{
HOST_WIDE_INT low = CONST_DOUBLE_LOW (op);
#if HOST_BITS_PER_WIDE_INT == 32
HOST_WIDE_INT high = CONST_DOUBLE_HIGH (op);
#endif
int i;
int last_bit_value;
int transitions = 0;
if ((low == 0
#if HOST_BITS_PER_WIDE_INT == 32
&& high == 0
#endif
)
|| (low == ~0
#if HOST_BITS_PER_WIDE_INT == 32
&& high == ~0
#endif
))
return 0;
last_bit_value = low & 1;
for (i = 1; i < HOST_BITS_PER_WIDE_INT; i++)
if (((low >>= 1) & 1) != last_bit_value)
last_bit_value ^= 1, transitions++;
#if HOST_BITS_PER_WIDE_INT == 32
if ((high & 1) != last_bit_value)
last_bit_value ^= 1, transitions++;
for (i = 1; i < HOST_BITS_PER_WIDE_INT; i++)
if (((high >>= 1) & 1) != last_bit_value)
last_bit_value ^= 1, transitions++;
#endif
return transitions <= 2;
lsb = low & -low;
return low == -lsb && (HOST_BITS_PER_WIDE_INT >= 64 || high == ~0);
}
else
return 0;
@ -3705,36 +3631,174 @@ includes_rshift_p (shiftop, andop)
return (INTVAL (andop) & ~shift_mask) == 0;
}
/* Return 1 if ANDOP is a mask that has no bits on that are not in the
mask required to convert the result of a rotate insn into a shift
left insn of SHIFTOP bits. */
/* Return 1 if ANDOP is a mask suitable for use with an rldic insn
to perform a left shift. It must have exactly SHIFTOP least
signifigant 0's, then one or more 1's, then zero or more 0's. */
int
includes_lshift64_p (shiftop, andop)
includes_rldic_lshift_p (shiftop, andop)
register rtx shiftop;
register rtx andop;
{
#if HOST_BITS_PER_WIDE_INT == 64
unsigned HOST_WIDE_INT shift_mask = ~(unsigned HOST_WIDE_INT) 0;
shift_mask <<= INTVAL (shiftop);
return (INTVAL (andop) & ~shift_mask) == 0;
#else
unsigned HOST_WIDE_INT shift_mask_low = ~(unsigned HOST_WIDE_INT) 0;
unsigned HOST_WIDE_INT shift_mask_high = ~(unsigned HOST_WIDE_INT) 0;
shift_mask_low <<= INTVAL (shiftop);
if (INTVAL (shiftop) > 32)
shift_mask_high <<= (INTVAL (shiftop) - 32);
if (GET_CODE (andop) == CONST_INT)
return (INTVAL (andop) & ~shift_mask_low) == 0;
{
unsigned HOST_WIDE_INT c, lsb, shift_mask;
c = INTVAL (andop);
if (c == 0 || c == ~(unsigned HOST_WIDE_INT) 0)
return 0;
shift_mask = ~(unsigned HOST_WIDE_INT) 0;
shift_mask <<= INTVAL (shiftop);
/* Find the least signifigant one bit. */
lsb = c & -c;
/* It must coincide with the LSB of the shift mask. */
if (-lsb != shift_mask)
return 0;
/* Invert to look for the next transition (if any). */
c = ~c;
/* Remove the low group of ones (originally low group of zeros). */
c &= -lsb;
/* Again find the lsb, and check we have all 1's above. */
lsb = c & -c;
return c == -lsb;
}
else if (GET_CODE (andop) == CONST_DOUBLE
&& (GET_MODE (andop) == VOIDmode || GET_MODE (andop) == DImode))
{
unsigned HOST_WIDE_INT low, high, lsb;
unsigned HOST_WIDE_INT shift_mask_low, shift_mask_high;
low = CONST_DOUBLE_LOW (andop);
if (HOST_BITS_PER_WIDE_INT < 64)
high = CONST_DOUBLE_HIGH (andop);
if ((low == 0 && (HOST_BITS_PER_WIDE_INT >= 64 || high == 0))
|| (low == ~(unsigned HOST_WIDE_INT) 0
&& (HOST_BITS_PER_WIDE_INT >= 64
|| high == ~(unsigned HOST_WIDE_INT) 0)))
return 0;
if (HOST_BITS_PER_WIDE_INT < 64 && low == 0)
{
shift_mask_high = ~(unsigned HOST_WIDE_INT) 0;
if (INTVAL (shiftop) > 32)
shift_mask_high <<= INTVAL (shiftop) - 32;
lsb = high & -high;
if (-lsb != shift_mask_high || INTVAL (shiftop) < 32)
return 0;
high = ~high;
high &= -lsb;
lsb = high & -high;
return high == -lsb;
}
shift_mask_low = ~(unsigned HOST_WIDE_INT) 0;
shift_mask_low <<= INTVAL (shiftop);
lsb = low & -low;
if (-lsb != shift_mask_low)
return 0;
if (HOST_BITS_PER_WIDE_INT < 64)
high = ~high;
low = ~low;
low &= -lsb;
if (HOST_BITS_PER_WIDE_INT < 64 && low == 0)
{
lsb = high & -high;
return high == -lsb;
}
lsb = low & -low;
return low == -lsb && (HOST_BITS_PER_WIDE_INT >= 64 || high == ~0);
}
else
return ((CONST_DOUBLE_HIGH (andop) & ~shift_mask_high) == 0
&& (CONST_DOUBLE_LOW (andop) & ~shift_mask_low) == 0);
#endif
return 0;
}
/* Return 1 if ANDOP is a mask suitable for use with an rldicr insn
to perform a left shift. It must have SHIFTOP or more least
signifigant 0's, with the remainder of the word 1's. */
int
includes_rldicr_lshift_p (shiftop, andop)
register rtx shiftop;
register rtx andop;
{
if (GET_CODE (andop) == CONST_INT)
{
unsigned HOST_WIDE_INT c, lsb;
unsigned HOST_WIDE_INT shift_mask;
shift_mask = ~(unsigned HOST_WIDE_INT) 0;
shift_mask <<= INTVAL (shiftop);
c = INTVAL (andop);
/* Find the least signifigant one bit. */
lsb = c & -c;
/* It must be covered by the shift mask.
This test also rejects c == 0. */
if ((lsb & shift_mask) == 0)
return 0;
/* Check we have all 1's above the transition, and reject all 1's. */
return c == -lsb && lsb != 1;
}
else if (GET_CODE (andop) == CONST_DOUBLE
&& (GET_MODE (andop) == VOIDmode || GET_MODE (andop) == DImode))
{
unsigned HOST_WIDE_INT low, lsb, shift_mask_low;
low = CONST_DOUBLE_LOW (andop);
if (HOST_BITS_PER_WIDE_INT < 64)
{
unsigned HOST_WIDE_INT high, shift_mask_high;
high = CONST_DOUBLE_HIGH (andop);
if (low == 0)
{
shift_mask_high = ~(unsigned HOST_WIDE_INT) 0;
if (INTVAL (shiftop) > 32)
shift_mask_high <<= INTVAL (shiftop) - 32;
lsb = high & -high;
if ((lsb & shift_mask_high) == 0)
return 0;
return high == -lsb;
}
if (high != ~0)
return 0;
}
shift_mask_low = ~(unsigned HOST_WIDE_INT) 0;
shift_mask_low <<= INTVAL (shiftop);
lsb = low & -low;
if ((lsb & shift_mask_low) == 0)
return 0;
return low == -lsb && lsb != 1;
}
else
return 0;
}
/* Return 1 if REGNO (reg1) == REGNO (reg2) - 1 making them candidates
@ -4537,9 +4601,6 @@ print_operand (file, x, code)
case 'W':
/* MB value for a PowerPC64 rldic operand. */
if (! rldic_operand (x, VOIDmode))
output_operand_lossage ("invalid %%W value");
val = (GET_CODE (x) == CONST_INT
? INTVAL (x) : CONST_DOUBLE_HIGH (x));

View File

@ -2585,7 +2585,6 @@ do { \
{"non_logical_cint_operand", {CONST_INT, CONST_DOUBLE}}, \
{"mask_operand", {CONST_INT}}, \
{"mask64_operand", {CONST_INT, CONST_DOUBLE}}, \
{"rldic_operand", {CONST_INT, CONST_DOUBLE}}, \
{"count_register_operand", {REG}}, \
{"xer_operand", {REG}}, \
{"call_operand", {SYMBOL_REF, REG}}, \

View File

@ -6559,8 +6559,8 @@
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
(and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "const_int_operand" "i"))
(match_operand:DI 3 "rldic_operand" "n")))]
"TARGET_POWERPC64 && includes_lshift64_p (operands[2], operands[3])"
(match_operand:DI 3 "const_int_operand" "n")))]
"TARGET_POWERPC64 && includes_rldic_lshift_p (operands[2], operands[3])"
"rldic %0,%1,%H2,%W3")
(define_insn "ashldi3_internal5"
@ -6568,10 +6568,10 @@
(compare:CC
(and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "const_int_operand" "i,i"))
(match_operand:DI 3 "rldic_operand" "n,n"))
(match_operand:DI 3 "const_int_operand" "n,n"))
(const_int 0)))
(clobber (match_scratch:DI 4 "=r,r"))]
"TARGET_POWERPC64 && includes_lshift64_p (operands[2], operands[3])"
"TARGET_POWERPC64 && includes_rldic_lshift_p (operands[2], operands[3])"
"@
rldic. %4,%1,%H2,%W3
#"
@ -6583,10 +6583,11 @@
(compare:CC
(and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "")
(match_operand:SI 2 "const_int_operand" ""))
(match_operand:DI 3 "rldic_operand" ""))
(match_operand:DI 3 "const_int_operand" ""))
(const_int 0)))
(clobber (match_scratch:DI 4 ""))]
"TARGET_POWERPC64 && includes_lshift64_p (operands[2], operands[3]) && reload_completed"
"TARGET_POWERPC64 && reload_completed
&& includes_rldic_lshift_p (operands[2], operands[3])"
[(set (match_dup 4)
(and:DI (ashift:DI (match_dup 1) (match_dup 2))
(match_dup 3)))
@ -6600,11 +6601,11 @@
(compare:CC
(and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "const_int_operand" "i,i"))
(match_operand:DI 3 "rldic_operand" "n,n"))
(match_operand:DI 3 "const_int_operand" "n,n"))
(const_int 0)))
(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
(and:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
"TARGET_POWERPC64 && includes_lshift64_p (operands[2], operands[3])"
"TARGET_POWERPC64 && includes_rldic_lshift_p (operands[2], operands[3])"
"@
rldic. %0,%1,%H2,%W3
#"
@ -6616,11 +6617,88 @@
(compare:CC
(and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "")
(match_operand:SI 2 "const_int_operand" ""))
(match_operand:DI 3 "rldic_operand" ""))
(match_operand:DI 3 "const_int_operand" ""))
(const_int 0)))
(set (match_operand:DI 0 "gpc_reg_operand" "")
(and:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
"TARGET_POWERPC64 && includes_lshift64_p (operands[2], operands[3]) && reload_completed"
"TARGET_POWERPC64 && reload_completed
&& includes_rldic_lshift_p (operands[2], operands[3])"
[(set (match_dup 0)
(and:DI (ashift:DI (match_dup 1) (match_dup 2))
(match_dup 3)))
(set (match_dup 4)
(compare:CC (match_dup 0)
(const_int 0)))]
"")
(define_insn "*ashldi3_internal7"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
(and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "const_int_operand" "i"))
(match_operand:DI 3 "mask64_operand" "S")))]
"TARGET_POWERPC64 && includes_rldicr_lshift_p (operands[2], operands[3])"
"rldicr %0,%1,%H2,%S3")
(define_insn "ashldi3_internal8"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
(compare:CC
(and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "const_int_operand" "i,i"))
(match_operand:DI 3 "mask64_operand" "S,S"))
(const_int 0)))
(clobber (match_scratch:DI 4 "=r,r"))]
"TARGET_POWERPC64 && includes_rldicr_lshift_p (operands[2], operands[3])"
"@
rldicr. %4,%1,%H2,%S3
#"
[(set_attr "type" "delayed_compare")
(set_attr "length" "4,8")])
(define_split
[(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
(compare:CC
(and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "")
(match_operand:SI 2 "const_int_operand" ""))
(match_operand:DI 3 "mask64_operand" ""))
(const_int 0)))
(clobber (match_scratch:DI 4 ""))]
"TARGET_POWERPC64 && reload_completed
&& includes_rldicr_lshift_p (operands[2], operands[3])"
[(set (match_dup 4)
(and:DI (ashift:DI (match_dup 1) (match_dup 2))
(match_dup 3)))
(set (match_dup 0)
(compare:CC (match_dup 4)
(const_int 0)))]
"")
(define_insn "*ashldi3_internal9"
[(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
(compare:CC
(and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "const_int_operand" "i,i"))
(match_operand:DI 3 "mask64_operand" "S,S"))
(const_int 0)))
(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
(and:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
"TARGET_POWERPC64 && includes_rldicr_lshift_p (operands[2], operands[3])"
"@
rldicr. %0,%1,%H2,%S3
#"
[(set_attr "type" "delayed_compare")
(set_attr "length" "4,8")])
(define_split
[(set (match_operand:CC 4 "cc_reg_not_cr0_operand" "")
(compare:CC
(and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "")
(match_operand:SI 2 "const_int_operand" ""))
(match_operand:DI 3 "mask64_operand" ""))
(const_int 0)))
(set (match_operand:DI 0 "gpc_reg_operand" "")
(and:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
"TARGET_POWERPC64 && reload_completed
&& includes_rldicr_lshift_p (operands[2], operands[3])"
[(set (match_dup 0)
(and:DI (ashift:DI (match_dup 1) (match_dup 2))
(match_dup 3)))