David Edelsohn wrote:
Paolo Bonzini writes:
Paolo> I'm testing a patch that does this replacement, and I can post it
Paolo> tomorrow morning. It has triggered only a dozen times so far (half in
Paolo> libgcc, half in the compiler), but it may be worth keeping it.
It would be nice to keep this type of optimization if the
re-engineered version works.
Here it is, bootstrapped and regtested on powerpc-apple-darwin8.1.0.
Ok for mainline?
Paolo
2005-08-22 Paolo Bonzini <[EMAIL PROTECTED]>
* config/rs6000/predicates.md (equality_operator): New.
* config/rs6000/rs6000.md: Rewrite as a peephole2 the split for
comparison with a large constant.
Index: config/rs6000/predicates.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/predicates.md,v
retrieving revision 1.23
diff -p -u -r1.23 predicates.md
--- config/rs6000/predicates.md 11 Aug 2005 21:18:11 -0000 1.23
+++ config/rs6000/predicates.md 22 Aug 2005 20:44:32 -0000
@@ -710,6 +710,10 @@
(define_predicate "boolean_or_operator"
(match_code "ior,xor"))
+;; Return true if operand is an equality operator.
+(define_special_predicate "equality_operator"
+ (match_code "eq,ne"))
+
;; Return true if operand is MIN or MAX operator.
(define_predicate "min_max_operator"
(match_code "smin,smax,umin,umax"))
Index: rs6000.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.md,v
retrieving revision 1.400
diff -p -u -r1.400 rs6000.md
--- rs6000.md 20 Aug 2005 04:17:17 -0000 1.400
+++ rs6000.md 22 Aug 2005 20:41:44 -0000
@@ -10727,32 +10727,43 @@
[(set_attr "type" "cmp")])
;; If we are comparing a register for equality with a large constant,
-;; we can do this with an XOR followed by a compare. But we need a scratch
-;; register for the result of the XOR.
-
-(define_split
- [(set (match_operand:CC 0 "cc_reg_operand" "")
- (compare:CC (match_operand:SI 1 "gpc_reg_operand" "")
- (match_operand:SI 2 "non_short_cint_operand" "")))
- (clobber (match_operand:SI 3 "gpc_reg_operand" ""))]
- "find_single_use (operands[0], insn, 0)
- && (GET_CODE (*find_single_use (operands[0], insn, 0)) == EQ
- || GET_CODE (*find_single_use (operands[0], insn, 0)) == NE)"
- [(set (match_dup 3) (xor:SI (match_dup 1) (match_dup 4)))
- (set (match_dup 0) (compare:CC (match_dup 3) (match_dup 5)))]
- "
-{
- /* Get the constant we are comparing against, C, and see what it looks like
- sign-extended to 16 bits. Then see what constant could be XOR'ed
- with C to get the sign-extended value. */
-
- HOST_WIDE_INT c = INTVAL (operands[2]);
+;; we can do this with an XOR followed by a compare. But this is profitable
+;; only if the large constant is only used for the comparison (and in this
+;; case we already have a register to reuse as scratch).
+
+(define_peephole2
+ [(set (match_operand:GPR 0 "register_operand")
+ (match_operand:GPR 1 "logical_operand" ""))
+ (set (match_dup 0) (match_operator:GPR 3 "boolean_or_operator"
+ [(match_dup 0)
+ (match_operand:GPR 2 "logical_operand" "")]))
+ (set (match_operand:CC 4 "cc_reg_operand" "")
+ (compare:CC (match_operand:GPR 5 "gpc_reg_operand" "")
+ (match_dup 0)))
+ (set (pc)
+ (if_then_else (match_operator 6 "equality_operator"
+ [(match_dup 4) (const_int 0)])
+ (match_operand 7 "" "")
+ (match_operand 8 "" "")))]
+ "peep2_reg_dead_p (3, operands[0])"
+ [(set (match_dup 0) (xor:GPR (match_dup 5) (match_dup 9)))
+ (set (match_dup 4) (compare:CC (match_dup 0) (match_dup 10)))
+ (set (pc) (if_then_else (match_dup 6) (match_dup 7) (match_dup 8)))]
+
+{
+ /* Get the constant we are comparing against, and see what it looks like
+ when sign-extended from 16 to 32 bits. Then see what constant we could
+ XOR with SEXTC to get the sign-extended value. */
+ rtx cnst = simplify_const_binary_operation (GET_CODE (operands[3]),
+ GET_MODE (operands[3]),
+ operands[1], operands[2]);
+ HOST_WIDE_INT c = INTVAL (cnst);
HOST_WIDE_INT sextc = ((c & 0xffff) ^ 0x8000) - 0x8000;
HOST_WIDE_INT xorv = c ^ sextc;
- operands[4] = GEN_INT (xorv);
- operands[5] = GEN_INT (sextc);
-}")
+ operands[9] = GEN_INT (xorv);
+ operands[10] = GEN_INT (sextc);
+})
(define_insn "*cmpsi_internal2"
[(set (match_operand:CCUNS 0 "cc_reg_operand" "=y")