[PATCH] Fix target/19147: invalid rlwinm patterns

Alan Modra amodra@bigpond.net.au
Fri Dec 24 13:47:00 GMT 2004


gcc.c-torture/execute/930718-1.c has been failing on powerpc64-linux
since somewhere in the latter half of September, and I hadn't got around
to investigating the reason.  It turns out that this failure is due to a
problem with andsi3_internal7 and andsi3_internal8, two patterns dealing
with wrapping rlwinm masks (ie. mb > me) I added to rs6000.md on
2002-07-24.  Fariborz Jahanian made a fix for one failure mode of
andsi3_internal8 on 2004-10-26, and at the time I commented that LT and
GT condition bits might be wrong before his patch.

Well, they're still wrong.  To get LT right, you must have a mask that
wraps over the high bits, but we go out of our way to ensure that the
mask doesn't wrap (to make EQ right).  A wrapping mask won't do for EQ
because "rlwinm." works by duplicating the 32-bit input to both high and
low word of a 64-bit value, rotating by 0 to 31 bits, then masking with
a pattern consisting of 1's between two given bits in the low word and
0's elsewhere.  The trickiness is that if the start bit of the mask is
less signifigant than the end bit, then the mask wraps around.  If the
mask wraps then the high word of the mask will be 1's, which will result
in EQ false if any bit of the input is set.  On the other hand, without
a wrapping mask LT will always be false regardless of input.

One solution to this dilemma is to rotate the input so that we can use
a non-wrapping mask to clear bits, then rotate back and use a wrapping
mask of all 1's to generate the condition bits.  That gets EQ, LT and
GT correct.  Unfortunately, if the output is wanted we've just
duplicated the low word to the high word, and I think GCC "knows" that
an andsi operation doesn't set bits willy nilly in the high word.  (See
rtlanal.c:nonzero_bits).

So..

	PR target/19147
	* config/rs6000/rs6000.md (andsi3_internal7, andsi3_internal8): Delete.

OK mainline, 3.4 and 3.3?

Index: gcc/config/rs6000/rs6000.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.md,v
retrieving revision 1.337
diff -u -p -r1.337 rs6000.md
--- gcc/config/rs6000/rs6000.md	11 Dec 2004 17:37:25 -0000	1.337
+++ gcc/config/rs6000/rs6000.md	24 Dec 2004 13:42:00 -0000
@@ -2411,60 +2411,6 @@
 }"
   [(set_attr "length" "8")])
 
-(define_insn_and_split "*andsi3_internal7"
-  [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
-	(compare:CC (and:SI (match_operand:SI 0 "gpc_reg_operand" "r,r")
-			    (match_operand:SI 1 "mask_operand_wrap" "i,i"))
-		    (const_int 0)))
-   (clobber (match_scratch:SI 3 "=r,r"))]
-  "TARGET_POWERPC64"
-  "#"
-  "TARGET_POWERPC64"
-  [(parallel [(set (match_dup 2)
-		   (compare:CC (and:SI (rotate:SI (match_dup 0) (match_dup 4))
-				       (match_dup 5))
-			       (const_int 0)))
-	      (clobber (match_dup 3))])]
-  "
-{
-  int mb = extract_MB (operands[1]);
-  int me = extract_ME (operands[1]);
-  operands[4] = GEN_INT (me + 1);
-  operands[5] = GEN_INT (~((HOST_WIDE_INT) -1 << (33 + me - mb)));
-}"
-  [(set_attr "type" "delayed_compare,compare")
-   (set_attr "length" "4,8")])
-
-(define_insn_and_split "*andsi3_internal8"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,??y")
-	(compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-			    (match_operand:SI 2 "mask_operand_wrap" "i,i"))
-		    (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-	(and:SI (match_dup 1)
-		(match_dup 2)))]
-  "TARGET_POWERPC64"
-  "#"
-  "TARGET_POWERPC64"
-  [(set (match_dup 0)
-		   (and:SI (rotate:SI (match_dup 1) (match_dup 4))
-			   (match_dup 5)))
-   (parallel [(set (match_dup 3)
-	           (compare:CC (rotate:SI (match_dup 0) (match_dup 6))
-			       (const_int 0)))
-              (set (match_dup 0)
-	           (rotate:SI (match_dup 0) (match_dup 6)))])]
-  "
-{
-  int mb = extract_MB (operands[2]);
-  int me = extract_ME (operands[2]);
-  operands[4] = GEN_INT (me + 1);
-  operands[6] = GEN_INT (32 - (me + 1));
-  operands[5] = GEN_INT (~((HOST_WIDE_INT) -1 << (33 + me - mb)));
-}"
-  [(set_attr "type" "delayed_compare,compare")
-   (set_attr "length" "8,12")])
-
 (define_expand "iorsi3"
   [(set (match_operand:SI 0 "gpc_reg_operand" "")
 	(ior:SI (match_operand:SI 1 "gpc_reg_operand" "")

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre



More information about the Gcc-patches mailing list