@@ -726,7 +726,7 @@
&& !satisfies_constraint_L (op)")))
;; Return 1 if the operand is a constant that can be used as the operand
-;; of an OR or XOR.
+;; of an AND, OR or XOR.
(define_predicate "logical_const_operand"
(match_code "const_int")
{
@@ -764,7 +764,11 @@
if (TARGET_POWERPC64)
{
- /* Fail if the mask is not 32-bit. */
+ /* Fail if the mask is not 32-bit. Note: If constraints are
+ implemented using mask_operand then they will never fail this
+ test. const_ints are VOIDmode, which is what is seen here
+ when called from a constraint. When called as a predicate,
+ the match_operand mode is seen. */
if (mode == DImode && (c & ~(unsigned HOST_WIDE_INT) 0xffffffff) != 0)
return 0;
@@ -16444,36 +16444,30 @@ includes_rshift_p (rtx shiftop, rtx andop)
int
includes_rldic_lshift_p (rtx shiftop, rtx andop)
{
- if (GET_CODE (andop) == CONST_INT)
- {
- unsigned HOST_WIDE_INT c, lsb, shift_mask;
+ unsigned HOST_WIDE_INT c, lsb, shift_mask;
- c = INTVAL (andop);
- if (c == 0 || c == HOST_WIDE_INT_M1U)
- return 0;
+ c = INTVAL (andop);
+ if (c == 0)
+ return 0;
- shift_mask = HOST_WIDE_INT_M1U;
- shift_mask <<= INTVAL (shiftop);
+ shift_mask = HOST_WIDE_INT_M1U << INTVAL (shiftop);
- /* Find the least significant one bit. */
- lsb = c & -c;
+ /* Find the least significant one bit. */
+ lsb = c & -c;
- /* It must coincide with the LSB of the shift mask. */
- if (-lsb != shift_mask)
- return 0;
+ /* 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;
+ /* Invert to look for the next transition (if any). */
+ c = ~c;
- /* Remove the low group of ones (originally low group of zeros). */
- c &= -lsb;
+ /* 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
- return 0;
+ /* Again find the lsb, and check we have all 1's above. */
+ lsb = c & -c;
+ return c == -lsb;
}
/* Return 1 if ANDOP is a mask suitable for use with an rldicr insn
@@ -16483,27 +16477,21 @@ includes_rldic_lshift_p (rtx shiftop, rtx andop)
int
includes_rldicr_lshift_p (rtx shiftop, rtx andop)
{
- if (GET_CODE (andop) == CONST_INT)
- {
- unsigned HOST_WIDE_INT c, lsb, shift_mask;
+ unsigned HOST_WIDE_INT c, lsb, shift_mask;
- shift_mask = HOST_WIDE_INT_M1U;
- shift_mask <<= INTVAL (shiftop);
- c = INTVAL (andop);
+ shift_mask = HOST_WIDE_INT_M1U << INTVAL (shiftop);
+ c = INTVAL (andop);
- /* Find the least significant 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;
+ /* Find the least significant one bit. */
+ lsb = c & -c;
- /* Check we have all 1's above the transition, and reject all 1's. */
- return c == -lsb && lsb != 1;
- }
- else
+ /* 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. */
+ return c == -lsb;
}
/* Return 1 if operands will generate a valid arguments to rlwimi
@@ -2921,6 +2921,9 @@
[(set_attr "type" "logical")
(set_attr "dot" "yes")])
+;; Differs from and<mode>3_imm_mask_dot in that if cr0 is not allocated
+;; the splitter will need to trash cr0. So choose and<mode>3_imm_mask_dot
+;; if possible.
(define_insn_and_split "*and<mode>3_imm_dot"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,??y")
(compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
@@ -2947,6 +2950,9 @@
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
+;; Differs from and<mode>3_imm_mask_dot2 in that if cr0 is not allocated
+;; the splitter will need to trash cr0. So choose and<mode>3_imm_mask_dot2
+;; if possible.
(define_insn_and_split "*and<mode>3_imm_dot2"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,??y")
(compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
@@ -3029,7 +3035,7 @@
(define_insn "*and<mode>3_mask"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
(and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
- (match_operand:GPR 2 "any_mask_operand" "S,T")))]
+ (match_operand:GPR 2 "any_mask_operand" "S,n")))]
""
"@
rldic%B2 %0,%1,0,%S2
@@ -3039,12 +3045,11 @@
(define_insn_and_split "*and<mode>3_mask_dot"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
(compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r,r,r")
- (match_operand:GPR 2 "any_mask_operand" "S,T,S,T"))
+ (match_operand:GPR 2 "any_mask_operand" "S,n,S,n"))
(const_int 0)))
(clobber (match_scratch:GPR 0 "=r,r,r,r"))]
"(<MODE>mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff)
- && rs6000_gen_cell_microcode
- && !logical_const_operand (operands[2], <MODE>mode)"
+ && rs6000_gen_cell_microcode"
"@
rldic%B2. %0,%1,0,%S2
rlwinm. %0,%1,0,%m2,%M2
@@ -3065,14 +3070,13 @@
(define_insn_and_split "*and<mode>3_mask_dot2"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
(compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r,r,r")
- (match_operand:GPR 2 "any_mask_operand" "S,T,S,T"))
+ (match_operand:GPR 2 "any_mask_operand" "S,n,S,n"))
(const_int 0)))
(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r,r,r")
(and:GPR (match_dup 1)
(match_dup 2)))]
"(<MODE>mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff)
- && rs6000_gen_cell_microcode
- && !logical_const_operand (operands[2], <MODE>mode)"
+ && rs6000_gen_cell_microcode"
"@
rldic%B2. %0,%1,0,%S2
rlwinm. %0,%1,0,%m2,%M2
@@ -3091,18 +3095,6 @@
(set_attr "length" "4,4,8,8")])
-
-(define_insn "andsi3_internal0_nomc"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
- (and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r")
- (match_operand:SI 2 "and_operand" "?r,T")))]
- "!rs6000_gen_cell_microcode"
- "@
- and %0,%1,%2
- rlwinm %0,%1,0,%m2,%M2"
- [(set_attr "type" "logical,shift")])
-
-
;; Handle the PowerPC64 rlwinm corner case
(define_insn_and_split "*andsi3_internal6"
@@ -5786,7 +5778,7 @@
(define_insn "*rotldi3_internal4"
[(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" "rn"))
+ (match_operand:SI 2 "reg_or_cint_operand" "rn"))
(match_operand:DI 3 "mask64_operand" "n")))]
"TARGET_POWERPC64"
"rld%I2c%B3 %0,%1,%H2,%S3"
@@ -5797,7 +5789,7 @@
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
(compare:CC (and:DI
(rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
- (match_operand:DI 2 "reg_or_cint_operand" "rn,rn"))
+ (match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
(match_operand:DI 3 "mask64_operand" "n,n"))
(const_int 0)))
(clobber (match_scratch:DI 4 "=r,r"))]
@@ -5814,7 +5806,7 @@
[(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
(compare:CC (and:DI
(rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
- (match_operand:DI 2 "reg_or_cint_operand" ""))
+ (match_operand:SI 2 "reg_or_cint_operand" ""))
(match_operand:DI 3 "mask64_operand" ""))
(const_int 0)))
(clobber (match_scratch:DI 4 ""))]
@@ -5832,7 +5824,7 @@
[(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
(compare:CC (and:DI
(rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
- (match_operand:DI 2 "reg_or_cint_operand" "rn,rn"))
+ (match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
(match_operand:DI 3 "mask64_operand" "n,n"))
(const_int 0)))
(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
@@ -5850,7 +5842,7 @@
[(set (match_operand:CC 4 "cc_reg_not_micro_cr0_operand" "")
(compare:CC (and:DI
(rotate:DI (match_operand:DI 1 "gpc_reg_operand" "")
- (match_operand:DI 2 "reg_or_cint_operand" ""))
+ (match_operand:SI 2 "reg_or_cint_operand" ""))
(match_operand:DI 3 "mask64_operand" ""))
(const_int 0)))
(set (match_operand:DI 0 "gpc_reg_operand" "")
@@ -5947,7 +5939,7 @@
[(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" "n")))]
+ (match_operand:DI 3 "const_int_operand" "n")))]
"TARGET_POWERPC64 && includes_rldicr_lshift_p (operands[2], operands[3])"
"rldicr %0,%1,%H2,%S3"
[(set_attr "type" "shift")])
@@ -5957,7 +5949,7 @@
(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" "n,n"))
+ (match_operand:DI 3 "const_int_operand" "n,n"))
(const_int 0)))
(clobber (match_scratch:DI 4 "=r,r"))]
"TARGET_64BIT && includes_rldicr_lshift_p (operands[2], operands[3])"
@@ -5973,7 +5965,7 @@
(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" ""))
+ (match_operand:DI 3 "const_int_operand" ""))
(const_int 0)))
(clobber (match_scratch:DI 4 ""))]
"TARGET_POWERPC64 && reload_completed
@@ -5991,7 +5983,7 @@
(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" "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)))]
@@ -6008,7 +6000,7 @@
(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" ""))
+ (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)))]
new file mode 100644
@@ -0,0 +1,8 @@
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-not "rotldi" } } */
+
+unsigned long f (unsigned long x)
+{
+ return ((x << 1) | (x >> 63)) & 0xffffffff;
+}