(and (not (match_operand 0 "logical_operand"))
(match_operand 0 "reg_or_logical_cint_operand"))))
-;; For SImode, return 1 if op is a constant that can be encoded in a
-;; 32-bit mask (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.
-;; For DImode, return 1 if the operand is a constant that is a
-;; PowerPC64 mask (no more than one 1->0 or 0->1 transitions). Reject
-;; all zeros, since zero should have been optimized away and confuses
-;; the making of MB and ME.
+;; Return 1 if op is a constant that can be encoded in a 32-bit mask,
+;; suitable for use with rlwinm (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.
(define_predicate "mask_operand"
(match_code "const_int")
{
c = INTVAL (op);
- /* Fail in 64-bit mode if the mask wraps around because the upper
- 32-bits of the mask will all be 1s, contrary to GCC's internal view. */
- if (mode == SImode && TARGET_POWERPC64 && (c & 0x80000001) == 0x80000001)
- return 0;
+ if (TARGET_POWERPC64)
+ {
+ /* Fail if the mask is not 32-bit. */
+ if (mode == DImode && (c & ~(unsigned HOST_WIDE_INT) 0xffffffff) != 0)
+ return 0;
- /* Reject all zeros or all ones in 32-bit mode. */
- if (c == 0 || (mode == SImode && c == -1))
- return 0;
+ /* Fail if the mask wraps around because the upper 32-bits of the
+ mask will all be 1s, contrary to GCC's internal view. */
+ if ((c & 0x80000001) == 0x80000001)
+ return 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;
+
/* Find the first transition. */
lsb = c & -c;
- if (mode == SImode)
- {
- /* Invert to look for a second transition. */
- c = ~c;
+ /* Invert to look for a second transition. */
+ c = ~c;
- /* Erase first transition. */
- c &= -lsb;
+ /* Erase first transition. */
+ c &= -lsb;
- /* Find the second transition (if any). */
- lsb = c & -c;
- }
+ /* 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 c == -lsb;
})
-;; Like mask_operand, but allow up to three transitions. This
+;; Return 1 if the operand is a constant that is a PowerPC64 mask
+;; suitable for use with rldicl or rldicr (no more than one 1->0 or 0->1
+;; transition). Reject all zeros, since zero should have been
+;; optimized away and confuses the making of MB and ME.
+(define_predicate "mask64_operand"
+ (match_code "const_int")
+{
+ HOST_WIDE_INT c, lsb;
+
+ c = INTVAL (op);
+
+ /* Reject all zeros. */
+ if (c == 0)
+ return 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;
+
+ /* Find the first transition. */
+ lsb = c & -c;
+
+ /* Match if all the bits above are 1's (or c is zero). */
+ return c == -lsb;
+})
+
+;; Like mask64_operand, but allow up to three transitions. This
;; predicate is used by insn patterns that generate two rldicl or
;; rldicr machine insns.
(define_predicate "mask64_2_operand"
(match_code "const_int")
{
- return mask64_1or2_operand (op, mode, false);
+ HOST_WIDE_INT c, lsb;
+
+ c = INTVAL (op);
+
+ /* Disallow all zeros. */
+ if (c == 0)
+ return 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;
+
+ /* Find the first transition. */
+ lsb = c & -c;
+
+ /* Invert to look for a second transition. */
+ c = ~c;
+
+ /* Erase first transition. */
+ c &= -lsb;
+
+ /* Find the second transition. */
+ lsb = c & -c;
+
+ /* Invert to look for a third transition. */
+ c = ~c;
+
+ /* Erase second transition. */
+ c &= -lsb;
+
+ /* Find the third transition (if any). */
+ lsb = c & -c;
+
+ /* Match if all the bits above are 1's (or c is zero). */
+ return c == -lsb;
})
;; Like and_operand, but also match constants that can be implemented
;; with two rldicl or rldicr insns.
(define_predicate "and64_2_operand"
- (ior (and (match_code "const_int")
- (match_test "mask64_1or2_operand (op, mode, true)"))
+ (ior (match_operand 0 "mask64_2_operand")
(if_then_else (match_test "fixed_regs[CR0_REGNO]")
(match_operand 0 "gpc_reg_operand")
(match_operand 0 "logical_operand"))))
;; constant that can be used as the operand of a logical AND.
(define_predicate "and_operand"
(ior (match_operand 0 "mask_operand")
- (if_then_else (match_test "fixed_regs[CR0_REGNO]")
- (match_operand 0 "gpc_reg_operand")
- (match_operand 0 "logical_operand"))))
+ (ior (and (match_test "TARGET_POWERPC64 && mode == DImode")
+ (match_operand 0 "mask64_operand"))
+ (if_then_else (match_test "fixed_regs[CR0_REGNO]")
+ (match_operand 0 "gpc_reg_operand")
+ (match_operand 0 "logical_operand")))))
;; Return 1 if the operand is either a logical operand or a short cint operand.
(define_predicate "scc_eq_operand"
case CONST_INT:
#if HOST_BITS_PER_WIDE_INT == 64
if ((INTVAL (op) >> 31) != 0 && (INTVAL (op) >> 31) != -1
- && mask_operand (op, mode))
+ && mask64_operand (op, mode))
return 2;
else
#endif
|| (high == -1 && low < 0))
return num_insns_constant_wide (low);
- else if (mask_operand (op, mode))
+ else if (mask64_operand (op, mode))
return 2;
else if (low == 0)
emit_move_insn (target, adjust_address_nv (mem, inner_mode, 0));
}
-int
-mask64_1or2_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED,
- bool allow_one)
-{
- if (GET_CODE (op) == CONST_INT)
- {
- HOST_WIDE_INT c, lsb;
- bool one_ok;
-
- c = INTVAL (op);
-
- /* Disallow all zeros. */
- if (c == 0)
- return 0;
-
- /* We can use a single rlwinm insn if no upper bits of C are set
- AND there are zero, one or two transitions in the _whole_ of
- C. */
- one_ok = !(c & ~(HOST_WIDE_INT)0xffffffff);
-
- /* 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;
-
- /* Find the first transition. */
- lsb = c & -c;
-
- /* Invert to look for a second transition. */
- c = ~c;
-
- /* Erase first transition. */
- c &= -lsb;
-
- /* Find the second transition. */
- lsb = c & -c;
-
- /* Invert to look for a third transition. */
- c = ~c;
-
- /* Erase second transition. */
- c &= -lsb;
-
- if (one_ok && !(allow_one || c))
- return 0;
-
- /* Find the third transition (if any). */
- lsb = c & -c;
-
- /* Match if all the bits above are 1's (or c is zero). */
- return c == -lsb;
- }
- return 0;
-}
-
/* Generates shifts and masks for a pair of rldicl or rldicr insns to
implement ANDing by the mask IN. */
void
/* PowerPC64 mask position. All 0's is excluded.
CONST_INT 32-bit mask is considered sign-extended so any
transition must occur within the CONST_INT, not on the boundary. */
- if (! mask_operand (x, DImode))
+ if (! mask64_operand (x, DImode))
output_operand_lossage ("invalid %%S value");
uval = INT_LOWPART (x);
&& (CONST_OK_FOR_LETTER_P (INTVAL (x), 'K')
|| (CONST_OK_FOR_LETTER_P (INTVAL (x),
mode == SImode ? 'L' : 'J'))
- || mask_operand (x, VOIDmode)))
+ || mask_operand (x, mode)
+ || (mode == DImode
+ && mask64_operand (x, DImode))))
|| ((outer_code == IOR || outer_code == XOR)
&& (CONST_OK_FOR_LETTER_P (INTVAL (x), 'K')
|| (CONST_OK_FOR_LETTER_P (INTVAL (x),
&& ((outer_code == AND
&& (CONST_OK_FOR_LETTER_P (INTVAL (x), 'K')
|| CONST_OK_FOR_LETTER_P (INTVAL (x), 'L')
- || mask_operand (x, DImode)))
+ || mask_operand (x, DImode)
+ || mask64_operand (x, DImode)))
|| ((outer_code == IOR || outer_code == XOR)
&& CONST_DOUBLE_HIGH (x) == 0
&& (CONST_DOUBLE_LOW (x)
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
(and:DI (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
(match_operand:DI 2 "reg_or_cint_operand" "ri"))
- (match_operand:DI 3 "mask_operand" "n")))]
+ (match_operand:DI 3 "mask64_operand" "n")))]
"TARGET_POWERPC64"
"rld%I2c%B3 %0,%1,%H2,%S3")
(compare:CC (and:DI
(rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
(match_operand:DI 2 "reg_or_cint_operand" "ri,ri"))
- (match_operand:DI 3 "mask_operand" "n,n"))
+ (match_operand:DI 3 "mask64_operand" "n,n"))
(const_int 0)))
(clobber (match_scratch:DI 4 "=r,r"))]
"TARGET_64BIT"
(compare:CC (and:DI
(rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
(match_operand:DI 2 "reg_or_cint_operand" ""))
- (match_operand:DI 3 "mask_operand" ""))
+ (match_operand:DI 3 "mask64_operand" ""))
(const_int 0)))
(clobber (match_scratch:DI 4 ""))]
"TARGET_POWERPC64 && reload_completed"
(compare:CC (and:DI
(rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
(match_operand:DI 2 "reg_or_cint_operand" "ri,ri"))
- (match_operand:DI 3 "mask_operand" "n,n"))
+ (match_operand:DI 3 "mask64_operand" "n,n"))
(const_int 0)))
(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
(and:DI (rotate:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
(compare:CC (and:DI
(rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
(match_operand:DI 2 "reg_or_cint_operand" ""))
- (match_operand:DI 3 "mask_operand" ""))
+ (match_operand:DI 3 "mask64_operand" ""))
(const_int 0)))
(set (match_operand:DI 0 "gpc_reg_operand" "")
(and:DI (rotate:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
[(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 "mask_operand" "n")))]
+ (match_operand:DI 3 "mask64_operand" "n")))]
"TARGET_POWERPC64 && includes_rldicr_lshift_p (operands[2], operands[3])"
"rldicr %0,%1,%H2,%S3")
(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 "mask_operand" "n,n"))
+ (match_operand:DI 3 "mask64_operand" "n,n"))
(const_int 0)))
(clobber (match_scratch:DI 4 "=r,r"))]
"TARGET_64BIT && includes_rldicr_lshift_p (operands[2], operands[3])"
(compare:CC
(and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "")
(match_operand:SI 2 "const_int_operand" ""))
- (match_operand:DI 3 "mask_operand" ""))
+ (match_operand:DI 3 "mask64_operand" ""))
(const_int 0)))
(clobber (match_scratch:DI 4 ""))]
"TARGET_POWERPC64 && reload_completed
(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 "mask_operand" "n,n"))
+ (match_operand:DI 3 "mask64_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)))]
(compare:CC
(and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "")
(match_operand:SI 2 "const_int_operand" ""))
- (match_operand:DI 3 "mask_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)))]
(clobber (match_scratch:CC 3 ""))]
"TARGET_POWERPC64
&& (fixed_regs[CR0_REGNO] || !logical_operand (operands[2], DImode))
- && !mask_operand (operands[2], DImode)"
+ && !mask_operand (operands[2], DImode)
+ && !mask64_operand (operands[2], DImode)"
[(set (match_dup 0)
(and:DI (rotate:DI (match_dup 1)
(match_dup 4))
})
(define_insn "*anddi3_internal2"
- [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,x,x,?y,?y,??y,??y,?y")
- (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r,r,r")
- (match_operand:DI 2 "and64_2_operand" "r,S,K,J,t,r,S,K,J,t"))
+ [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,x,x,x,?y,?y,?y,??y,??y,?y")
+ (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r,r,r,r,r")
+ (match_operand:DI 2 "and64_2_operand" "r,S,T,K,J,t,r,S,T,K,J,t"))
(const_int 0)))
- (clobber (match_scratch:DI 3 "=r,r,r,r,r,r,r,r,r,r"))
- (clobber (match_scratch:CC 4 "=X,X,X,X,X,X,X,x,x,X"))]
+ (clobber (match_scratch:DI 3 "=r,r,r,r,r,r,r,r,r,r,r,r"))
+ (clobber (match_scratch:CC 4 "=X,X,X,X,X,X,X,X,X,x,x,X"))]
"TARGET_64BIT"
"@
and. %3,%1,%2
rldic%B2. %3,%1,0,%S2
+ rlwinm. %3,%1,0,%m2,%M2
andi. %3,%1,%b2
andis. %3,%1,%u2
#
#
#
#
+ #
#"
- [(set_attr "type" "compare,delayed_compare,compare,compare,delayed_compare,compare,compare,compare,compare,compare")
- (set_attr "length" "4,4,4,4,8,8,8,8,8,12")])
+ [(set_attr "type" "compare,delayed_compare,delayed_compare,compare,compare,delayed_compare,delayed_compare,compare,compare,compare,compare,compare")
+ (set_attr "length" "4,4,4,4,4,8,8,8,8,8,8,12")])
(define_split
[(set (match_operand:CC 0 "cc_reg_operand" "")
(const_int 0)))
(clobber (match_scratch:DI 3 ""))
(clobber (match_scratch:CC 4 ""))]
- "TARGET_POWERPC64 && reload_completed
+ "TARGET_64BIT && reload_completed
&& (fixed_regs[CR0_REGNO] || !logical_operand (operands[2], DImode))
- && !mask_operand (operands[2], DImode)"
+ && !mask_operand (operands[2], DImode)
+ && !mask64_operand (operands[2], DImode)"
[(set (match_dup 3)
(and:DI (rotate:DI (match_dup 1)
(match_dup 5))
}")
(define_insn "*anddi3_internal3"
- [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,x,x,x,?y,?y,??y,??y,?y")
- (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r,r,r")
- (match_operand:DI 2 "and64_2_operand" "r,S,K,J,t,r,S,K,J,t"))
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,x,x,x,x,?y,?y,?y,??y,??y,?y")
+ (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r,r,r,r,r")
+ (match_operand:DI 2 "and64_2_operand" "r,S,T,K,J,t,r,S,T,K,J,t"))
(const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r,r,r,r,r,r")
+ (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r,r,r,r,r,r,r,r")
(and:DI (match_dup 1) (match_dup 2)))
- (clobber (match_scratch:CC 4 "=X,X,X,X,X,X,X,x,x,X"))]
+ (clobber (match_scratch:CC 4 "=X,X,X,X,X,X,X,X,X,x,x,X"))]
"TARGET_64BIT"
"@
and. %0,%1,%2
rldic%B2. %0,%1,0,%S2
+ rlwinm. %0,%1,0,%m2,%M2
andi. %0,%1,%b2
andis. %0,%1,%u2
#
#
#
#
+ #
#"
- [(set_attr "type" "compare,delayed_compare,compare,compare,delayed_compare,compare,compare,compare,compare,compare")
- (set_attr "length" "4,4,4,4,8,8,8,8,8,12")])
+ [(set_attr "type" "compare,delayed_compare,delayed_compare,compare,compare,delayed_compare,delayed_compare,compare,compare,compare,compare,compare")
+ (set_attr "length" "4,4,4,4,4,8,8,8,8,8,8,12")])
(define_split
[(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
(compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "")
- (match_operand:DI 2 "and_operand" ""))
+ (match_operand:DI 2 "and64_2_operand" ""))
(const_int 0)))
(set (match_operand:DI 0 "gpc_reg_operand" "")
(and:DI (match_dup 1) (match_dup 2)))
(clobber (match_scratch:CC 4 ""))]
- "TARGET_POWERPC64 && reload_completed"
+ "TARGET_64BIT && reload_completed"
[(parallel [(set (match_dup 0)
(and:DI (match_dup 1) (match_dup 2)))
(clobber (match_dup 4))])
(set (match_operand:DI 0 "gpc_reg_operand" "")
(and:DI (match_dup 1) (match_dup 2)))
(clobber (match_scratch:CC 4 ""))]
- "TARGET_POWERPC64 && reload_completed
+ "TARGET_64BIT && reload_completed
&& (fixed_regs[CR0_REGNO] || !logical_operand (operands[2], DImode))
- && !mask_operand (operands[2], DImode)"
+ && !mask_operand (operands[2], DImode)
+ && !mask64_operand (operands[2], DImode)"
[(set (match_dup 0)
(and:DI (rotate:DI (match_dup 1)
(match_dup 5))
;; Use (and:DI (rotate:DI ...)) to avoid anddi3 unnecessary clobber.
(define_split
[(set (match_operand:DI 0 "gpc_reg_operand" "")
- (match_operand:DI 1 "mask_operand" ""))]
+ (match_operand:DI 1 "mask64_operand" ""))]
"TARGET_POWERPC64 && num_insns_constant (operands[1], DImode) > 1"
[(set (match_dup 0) (const_int -1))
(set (match_dup 0)