;; SImode
-(define_insn "*mov_sidesi_biap"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (mem:SI (plus:SI
- (mult:SI (match_operand:SI 1 "register_operand" "r,r")
- (match_operand:SI 2 "const_int_operand" "n,n"))
- (match_operand:SI 3 "register_operand" "r,r"))))
+(define_insn "*mov_sidesisf_biap"
+ [(set (match_operand 0 "register_operand" "=r,r")
+ (mem (plus:SI
+ (mult:SI (match_operand:SI 1 "register_operand" "r,r")
+ (match_operand:SI 2 "const_int_operand" "n,n"))
+ (match_operand:SI 3 "register_operand" "r,r"))))
(set (match_operand:SI 4 "register_operand" "=*3,r")
(plus:SI (mult:SI (match_dup 1)
(match_dup 2))
(match_dup 3)))]
- "cris_side_effect_mode_ok (MULT, operands, 4, 3, 1, 2, 0)"
+ "GET_MODE_SIZE (GET_MODE (operands[0])) == UNITS_PER_WORD
+ && cris_side_effect_mode_ok (MULT, operands, 4, 3, 1, 2, 0)"
"@
#
move.%s0 [%4=%3+%1%T2],%0")
;; SImode
-(define_insn "*mov_sidesi"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r")
- (mem:SI
+(define_insn "*mov_sidesisf"
+ [(set (match_operand 0 "register_operand" "=r,r,r")
+ (mem
(plus:SI (match_operand:SI 1 "cris_bdap_operand" "%r,r,r")
(match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn"))))
(set (match_operand:SI 3 "register_operand" "=*1,r,r")
(plus:SI (match_dup 1)
(match_dup 2)))]
- "cris_side_effect_mode_ok (PLUS, operands, 3, 1, 2, -1, 0)"
+ "GET_MODE_SIZE (GET_MODE (operands[0])) == UNITS_PER_WORD
+ && cris_side_effect_mode_ok (PLUS, operands, 3, 1, 2, -1, 0)"
"*
{
if (which_alternative == 0
;; SImode
-(define_insn "*mov_sidesi_biap_mem"
- [(set (mem:SI (plus:SI
- (mult:SI (match_operand:SI 0 "register_operand" "r,r,r")
- (match_operand:SI 1 "const_int_operand" "n,n,n"))
- (match_operand:SI 2 "register_operand" "r,r,r")))
- (match_operand:SI 3 "register_operand" "r,r,r"))
+(define_insn "*mov_sidesisf_biap_mem"
+ [(set (mem (plus:SI
+ (mult:SI (match_operand:SI 0 "register_operand" "r,r,r")
+ (match_operand:SI 1 "const_int_operand" "n,n,n"))
+ (match_operand:SI 2 "register_operand" "r,r,r")))
+ (match_operand 3 "register_operand" "r,r,r"))
(set (match_operand:SI 4 "register_operand" "=*2,!3,r")
(plus:SI (mult:SI (match_dup 0)
(match_dup 1))
(match_dup 2)))]
- "cris_side_effect_mode_ok (MULT, operands, 4, 2, 0, 1, 3)"
+ "GET_MODE_SIZE (GET_MODE (operands[3])) == UNITS_PER_WORD
+ && cris_side_effect_mode_ok (MULT, operands, 4, 2, 0, 1, 3)"
"@
#
#
;; SImode
-(define_insn "*mov_sidesi_mem"
- [(set (mem:SI
+(define_insn "*mov_sidesisf_mem"
+ [(set (mem
(plus:SI (match_operand:SI 0 "cris_bdap_operand" "%r,r,r,r")
(match_operand:SI 1 "cris_bdap_operand" "r>Rn,r>Rn,r,>Rn")))
- (match_operand:SI 2 "register_operand" "r,r,r,r"))
+ (match_operand 2 "register_operand" "r,r,r,r"))
(set (match_operand:SI 3 "register_operand" "=*0,!2,r,r")
(plus:SI (match_dup 0)
(match_dup 1)))]
- "cris_side_effect_mode_ok (PLUS, operands, 3, 0, 1, -1, 2)"
+ "GET_MODE_SIZE (GET_MODE (operands[2])) == UNITS_PER_WORD
+ && cris_side_effect_mode_ok (PLUS, operands, 3, 0, 1, -1, 2)"
"*
{
if (which_alternative == 0
(match_operand:SI 2 "const_int_operand" ""))
(match_operand:SI 3 "register_operand" ""))]))
(set (match_operand:SI 4 "register_operand" "")
- (plus:SI (mult:SI (match_dup 1)
- (match_dup 2))
+ (plus:SI (mult:SI (match_dup 1)
+ (match_dup 2))
(match_dup 3)))])]
"REG_P (operands[3]) && REG_P (operands[4])
&& REGNO (operands[3]) == REGNO (operands[4])"
[(set (match_dup 4) (plus:SI (mult:SI (match_dup 1) (match_dup 2))
- (match_dup 3)))
+ (match_dup 3)))
(set (match_dup 0) (match_dup 5))]
"operands[5] = replace_equiv_address (operands[6], operands[3]);")
;; We have trouble with and:s and shifts. Maybe something is broken in
;; gcc? Or it could just be that bit-field insn expansion is a bit
;; suboptimal when not having extzv insns.
+;; Testcase for the following four peepholes: gcc.dg/cris-peep2-xsrand.c
-(define_peephole
- [(set (match_operand 0 "register_operand" "=r")
+(define_peephole2 ; asrandb (peephole casesi+31)
+ [(set (match_operand:SI 0 "register_operand" "")
(ashiftrt:SI (match_dup 0)
- (match_operand:SI 1 "const_int_operand" "n")))
+ (match_operand:SI 1 "const_int_operand" "")))
(set (match_dup 0)
(and:SI (match_dup 0)
- (match_operand 2 "const_int_operand" "n")))]
+ (match_operand 2 "const_int_operand" "")))]
"INTVAL (operands[2]) > 31
&& INTVAL (operands[2]) < 255
- && INTVAL (operands[1]) > 23"
-
-;; The m flag should be ignored, because this will be a *byte* "and"
-;; operation.
-
- "*
-{
- cc_status.flags |= CC_NOT_NEGATIVE;
-
- return \"lsrq %1,%0\;and.b %2,%0\";
-}")
-
-(define_peephole
- [(set (match_operand 0 "register_operand" "=r")
+ && INTVAL (operands[1]) > 23
+ /* Check that the and-operation enables us to use logical-shift. */
+ && (INTVAL (operands[2])
+ & ((HOST_WIDE_INT) -1 << (32 - INTVAL (operands[1])))) == 0"
+ [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1)))
+ (set (match_dup 3) (and:QI (match_dup 3) (match_dup 2)))]
+ ;; FIXME: CC0 is valid except for the M bit.
+ "operands[3] = gen_rtx_REG (QImode, REGNO (operands[0]));")
+
+(define_peephole2 ; asrandw (peephole casesi+32)
+ [(set (match_operand:SI 0 "register_operand" "")
(ashiftrt:SI (match_dup 0)
- (match_operand:SI 1 "const_int_operand" "n")))
+ (match_operand:SI 1 "const_int_operand" "")))
(set (match_dup 0)
- (and:SI (match_dup 0)
- (match_operand 2 "const_int_operand" "n")))]
+ (and:SI (match_dup 0) (match_operand 2 "const_int_operand" "")))]
"INTVAL (operands[2]) > 31
&& INTVAL (operands[2]) < 65535
&& INTVAL (operands[2]) != 255
- && INTVAL (operands[1]) > 15"
-
-;; The m flag should be ignored, because this will be a *word* "and"
-;; operation.
-
- "*
-{
- cc_status.flags |= CC_NOT_NEGATIVE;
-
- return \"lsrq %1,%0\;and.w %2,%0\";
-}")
-
-(define_peephole
- [(set (match_operand 0 "register_operand" "=r")
+ && INTVAL (operands[1]) > 15
+ /* Check that the and-operation enables us to use logical-shift. */
+ && (INTVAL (operands[2])
+ & ((HOST_WIDE_INT) -1 << (32 - INTVAL (operands[1])))) == 0"
+ [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1)))
+ (set (match_dup 3) (and:HI (match_dup 3) (match_dup 2)))]
+ ;; FIXME: CC0 is valid except for the M bit.
+ "operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));")
+
+(define_peephole2 ; lsrandb (peephole casesi+33)
+ [(set (match_operand:SI 0 "register_operand" "")
(lshiftrt:SI (match_dup 0)
- (match_operand:SI 1 "const_int_operand" "n")))
+ (match_operand:SI 1 "const_int_operand" "")))
(set (match_dup 0)
- (and:SI (match_dup 0)
- (match_operand 2 "const_int_operand" "n")))]
+ (and:SI (match_dup 0) (match_operand 2 "const_int_operand" "")))]
"INTVAL (operands[2]) > 31
&& INTVAL (operands[2]) < 255
&& INTVAL (operands[1]) > 23"
+ [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1)))
+ (set (match_dup 3) (and:QI (match_dup 3) (match_dup 2)))]
+ ;; FIXME: CC0 is valid except for the M bit.
+ "operands[3] = gen_rtx_REG (QImode, REGNO (operands[0]));")
-;; The m flag should be ignored, because this will be a *byte* "and"
-;; operation.
-
- "*
-{
- cc_status.flags |= CC_NOT_NEGATIVE;
-
- return \"lsrq %1,%0\;and.b %2,%0\";
-}")
-
-(define_peephole
- [(set (match_operand 0 "register_operand" "=r")
+(define_peephole2 ; lsrandw (peephole casesi+34)
+ [(set (match_operand:SI 0 "register_operand" "")
(lshiftrt:SI (match_dup 0)
- (match_operand:SI 1 "const_int_operand" "n")))
+ (match_operand:SI 1 "const_int_operand" "")))
(set (match_dup 0)
- (and:SI (match_dup 0)
- (match_operand 2 "const_int_operand" "n")))]
+ (and:SI (match_dup 0) (match_operand 2 "const_int_operand" "")))]
"INTVAL (operands[2]) > 31 && INTVAL (operands[2]) < 65535
&& INTVAL (operands[2]) != 255
&& INTVAL (operands[1]) > 15"
-
-;; The m flag should be ignored, because this will be a *word* "and"
-;; operation.
-
- "*
-{
- cc_status.flags |= CC_NOT_NEGATIVE;
-
- return \"lsrq %1,%0\;and.w %2,%0\";
-}")
+ [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1)))
+ (set (match_dup 3) (and:HI (match_dup 3) (match_dup 2)))]
+ ;; FIXME: CC0 is valid except for the M bit.
+ "operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));")
\f
;; Change
;; move [rx=rx+n],ry
;; when -128 <= n <= 127.
;; This will reduce the size of the assembler code for n = [-128..127],
-;; and speed up accordingly.
-
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "const_int_operand" "n")))
- (set (match_operand 3 "register_operand" "=r")
- (mem (match_dup 0)))]
- "GET_MODE (operands[3]) != DImode
- && REGNO (operands[3]) != REGNO (operands[0])
- && (BASE_P (operands[1]) || BASE_P (operands[2]))
- && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')
- && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
- && (INTVAL (operands[2]) >= -128 && INTVAL (operands[2]) < 128)"
- "move.%s3 [%0=%1%S2],%3")
+;; and speed up accordingly. Don't match if the previous insn is
+;; (set rx rz) because that combination is matched by another peephole.
+;; No stable test-case.
+
+(define_peephole2 ; moversideqi (peephole casesi+35)
+ [(set (match_operand:SI 0 "register_operand" "")
+ (plus:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "const_int_operand" "")))
+ (set (match_operand 3 "register_operand" "")
+ (match_operator 4 "cris_mem_op" [(match_dup 0)]))]
+ "GET_MODE_SIZE (GET_MODE (operands[4])) <= UNITS_PER_WORD
+ && REGNO (operands[3]) != REGNO (operands[0])
+ && (BASE_P (operands[1]) || BASE_P (operands[2]))
+ && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')
+ && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
+ && (INTVAL (operands[2]) >= -128 && INTVAL (operands[2]) < 128)"
+ [(parallel
+ [(set (match_dup 3) (match_dup 5))
+ (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])]
+ ;; Checking the previous insn is a bit too awkward for the condition.
+{
+ rtx prev = prev_nonnote_insn (curr_insn);
+ if (prev != NULL_RTX)
+ {
+ rtx set = single_set (prev);
+ if (set != NULL_RTX
+ && REG_S_P (SET_DEST (set))
+ && REGNO (SET_DEST (set)) == REGNO (operands[0])
+ && REG_S_P (SET_SRC (set)))
+ FAIL;
+ }
+ operands[5]
+ = replace_equiv_address (operands[4],
+ gen_rtx_PLUS (SImode,
+ operands[1], operands[2]));
+})
;; Vice versa: move ry,[rx=rx+n]
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "const_int_operand" "n")))
- (set (mem (match_dup 0))
- (match_operand 3 "register_operand" "=r"))]
- "GET_MODE (operands[3]) != DImode
- && REGNO (operands[3]) != REGNO (operands[0])
- && (BASE_P (operands[1]) || BASE_P (operands[2]))
- && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')
- && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
- && (INTVAL (operands[2]) >= -128 && INTVAL (operands[2]) < 128)"
- "move.%s3 %3,[%0=%1%S2]"
- [(set_attr "cc" "none")])
+(define_peephole2 ; movemsideqi (peephole casesi+36)
+ [(set (match_operand:SI 0 "register_operand" "")
+ (plus:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "const_int_operand" "")))
+ (set (match_operator 3 "cris_mem_op" [(match_dup 0)])
+ (match_operand 4 "register_operand" ""))]
+ "GET_MODE_SIZE (GET_MODE (operands[4])) <= UNITS_PER_WORD
+ && REGNO (operands[4]) != REGNO (operands[0])
+ && (BASE_P (operands[1]) || BASE_P (operands[2]))
+ && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')
+ && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
+ && (INTVAL (operands[2]) >= -128 && INTVAL (operands[2]) < 128)"
+ [(parallel
+ [(set (match_dup 5) (match_dup 4))
+ (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])]
+ "operands[5]
+ = replace_equiv_address (operands[3],
+ gen_rtx_PLUS (SImode,
+ operands[1], operands[2]));")
\f
;; As above, change:
;; add.d n,rx
;; out of hand. They probably will not save the time they take typing in,
;; not to mention the bugs that creep in. FIXME: Get rid of as many of
;; the splits and peepholes as possible.
-
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "const_int_operand" "n")))
- (set (match_operand 3 "register_operand" "=r")
- (match_operator 4 "cris_orthogonal_operator"
- [(match_dup 3)
- (mem (match_dup 0))]))]
+;; No stable test-case.
+
+(define_peephole2 ; mover2side (peephole casesi+37)
+ [(set (match_operand:SI 0 "register_operand" "")
+ (plus:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "const_int_operand" "")))
+ (set (match_operand 3 "register_operand" "")
+ (match_operator 4 "cris_orthogonal_operator"
+ [(match_dup 3)
+ (match_operator
+ 5 "cris_mem_op" [(match_dup 0)])]))]
"GET_MODE (operands[3]) != DImode
- && REGNO (operands[0]) != REGNO (operands[3])
- && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')
- && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
- && INTVAL (operands[2]) >= -128
- && INTVAL (operands[2]) <= 127"
- "%x4.%s3 [%0=%1%S2],%3")
+ && REGNO (operands[0]) != REGNO (operands[3])
+ && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')
+ && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
+ && INTVAL (operands[2]) >= -128
+ && INTVAL (operands[2]) <= 127"
+ [(parallel
+ [(set (match_dup 3) (match_op_dup 4 [(match_dup 3) (match_dup 6)]))
+ (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])]
+ "operands[6]
+ = replace_equiv_address (operands[5],
+ gen_rtx_PLUS (SImode,
+ operands[1], operands[2]));")
;; Sometimes, for some reason the pattern
;; move x,rx
;; add y,rx
;; move [rx],rz
;; will occur. Solve this, and likewise for to-memory.
+;; No stable test-case.
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
- (match_operand:SI 1 "cris_bdap_biap_operand" "r,>Rn,r,>Rn"))
+(define_peephole2 ; moverside (peephole casesi+38)
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "cris_bdap_biap_operand" ""))
(set (match_dup 0)
- (plus:SI (match_operand:SI 2 "cris_bdap_biap_operand" "0,0,r>Rn,r")
- (match_operand:SI 3 "cris_bdap_biap_operand" "r>Rn,r,0,0")))
- (set (match_operand 4 "register_operand" "=r,r,r,r")
- (mem (match_dup 0)))]
+ (plus:SI (match_operand:SI 2 "cris_bdap_biap_operand" "")
+ (match_operand:SI 3 "cris_bdap_biap_operand" "")))
+ (set (match_operand 4 "register_operand" "")
+ (match_operator 5 "cris_mem_op" [(match_dup 0)]))]
"(rtx_equal_p (operands[2], operands[0])
|| rtx_equal_p (operands[3], operands[0]))
&& cris_side_effect_mode_ok (PLUS, operands, 0,
- (REG_S_P (operands[1])
- ? 1
- : (rtx_equal_p (operands[2], operands[0])
- ? 3 : 2)),
- (! REG_S_P (operands[1])
- ? 1
- : (rtx_equal_p (operands[2], operands[0])
- ? 3 : 2)),
- -1, 4)"
- "@
- move.%s4 [%0=%1%S3],%4
- move.%s4 [%0=%3%S1],%4
- move.%s4 [%0=%1%S2],%4
- move.%s4 [%0=%2%S1],%4")
+ (REG_S_P (operands[1])
+ ? 1
+ : (rtx_equal_p (operands[2], operands[0])
+ ? 3 : 2)),
+ (! REG_S_P (operands[1])
+ ? 1
+ : (rtx_equal_p (operands[2], operands[0])
+ ? 3 : 2)),
+ -1, 4)"
+ [(parallel
+ [(set (match_dup 4) (match_dup 6))
+ (set (match_dup 0) (plus:SI (match_dup 7) (match_dup 8)))])]
+{
+ rtx reg
+ = rtx_equal_p (operands[2], operands[0]) ? operands[3] : operands[2];
+
+ if (REG_S_P (operands[1]))
+ {
+ operands[7] = operands[1];
+ operands[8] = reg;
+ }
+ else
+ {
+ operands[7] = reg;
+ operands[8] = operands[1];
+ }
+ operands[6]
+ = replace_equiv_address (operands[5],
+ gen_rtx_PLUS (SImode,
+ operands[7], operands[8]));
+})
;; As above but to memory.
+;; FIXME: Split movemside and moverside into variants and prune
+;; the ones that don't trig.
+;; No stable test-case.
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
- (match_operand:SI 1 "cris_bdap_biap_operand" "r,>Rn,r,>Rn"))
+(define_peephole2 ; movemside (peephole casesi+39)
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "cris_bdap_biap_operand" ""))
(set (match_dup 0)
- (plus:SI (match_operand:SI 2 "cris_bdap_biap_operand" "0,0,r>Rn,r")
- (match_operand:SI 3 "cris_bdap_biap_operand" "r>Rn,r,0,0")))
- (set (mem (match_dup 0))
- (match_operand 4 "register_operand" "=r,r,r,r"))]
+ (plus:SI (match_operand:SI 2 "cris_bdap_biap_operand" "")
+ (match_operand:SI 3 "cris_bdap_biap_operand" "")))
+ (set (match_operator 4 "cris_mem_op" [(match_dup 0)])
+ (match_operand 5 "register_operand" ""))]
"(rtx_equal_p (operands[2], operands[0])
|| rtx_equal_p (operands[3], operands[0]))
&& cris_side_effect_mode_ok (PLUS, operands, 0,
- (REG_S_P (operands[1])
- ? 1
- : (rtx_equal_p (operands[2], operands[0])
- ? 3 : 2)),
- (! REG_S_P (operands[1])
- ? 1
- : (rtx_equal_p (operands[2], operands[0])
- ? 3 : 2)),
- -1, 4)"
- "@
- move.%s4 %4,[%0=%1%S3]
- move.%s4 %4,[%0=%3%S1]
- move.%s4 %4,[%0=%1%S2]
- move.%s4 %4,[%0=%2%S1]"
- [(set_attr "cc" "none")])
-
-
-;; As the move from-memory above, but with an operation.
-
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
- (match_operand:SI 1 "cris_bdap_biap_operand" "r,>Rn,r,>Rn"))
- (set (match_dup 0)
- (plus:SI (match_operand:SI 2 "cris_bdap_biap_operand" "0,0,r>Rn,r")
- (match_operand:SI 3 "cris_bdap_biap_operand" "r>Rn,r,0,0")))
- (set (match_operand 4 "register_operand" "=r,r,r,r")
- (match_operator 5 "cris_orthogonal_operator"
- [(match_dup 3)
- (mem (match_dup 0))]))]
- "(rtx_equal_p (operands[2], operands[0])
- || rtx_equal_p (operands[3], operands[0]))
- && cris_side_effect_mode_ok (PLUS, operands, 0,
- (REG_S_P (operands[1])
- ? 1
- : (rtx_equal_p (operands[2], operands[0])
- ? 3 : 2)),
- (! REG_S_P (operands[1])
- ? 1
- : (rtx_equal_p (operands[2], operands[0])
- ? 3 : 2)),
- -1, 4)"
- "@
- %x5.%s4 [%0=%1%S3],%4
- %x5.%s4 [%0=%3%S1],%4
- %x5.%s4 [%0=%1%S2],%4
- %x5.%s4 [%0=%2%S1],%4")
-
-;; Same, but with swapped operands (and commutative operation).
+ (REG_S_P (operands[1])
+ ? 1
+ : (rtx_equal_p (operands[2], operands[0])
+ ? 3 : 2)),
+ (! REG_S_P (operands[1])
+ ? 1
+ : (rtx_equal_p (operands[2], operands[0])
+ ? 3 : 2)),
+ -1, 5)"
+ [(parallel
+ [(set (match_dup 6) (match_dup 5))
+ (set (match_dup 0) (plus:SI (match_dup 7) (match_dup 8)))])]
+{
+ rtx reg
+ = rtx_equal_p (operands[2], operands[0]) ? operands[3] : operands[2];
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
- (match_operand:SI 1 "cris_bdap_biap_operand" "r,>Rn,r,>Rn"))
- (set (match_dup 0)
- (plus:SI (match_operand:SI 2 "cris_bdap_biap_operand" "0,0,r>Rn,r")
- (match_operand:SI 3 "cris_bdap_biap_operand" "r>Rn,r,0,0")))
- (set (match_operand 4 "register_operand" "=r,r,r,r")
- (match_operator 5 "cris_commutative_orth_op"
- [(mem (match_dup 0))
- (match_dup 3)]))]
- "(rtx_equal_p (operands[2], operands[0])
- || rtx_equal_p (operands[3], operands[0]))
- && cris_side_effect_mode_ok (PLUS, operands, 0,
- (REG_S_P (operands[1])
- ? 1
- : (rtx_equal_p (operands[2], operands[0])
- ? 3 : 2)),
- (! REG_S_P (operands[1])
- ? 1
- : (rtx_equal_p (operands[2], operands[0])
- ? 3 : 2)),
- -1, 4)"
- "@
- %x5.%s4 [%0=%1%S3],%4
- %x5.%s4 [%0=%3%S1],%4
- %x5.%s4 [%0=%1%S2],%4
- %x5.%s4 [%0=%2%S1],%4")
+ if (REG_S_P (operands[1]))
+ {
+ operands[7] = operands[1];
+ operands[8] = reg;
+ }
+ else
+ {
+ operands[7] = reg;
+ operands[8] = operands[1];
+ }
+ operands[6]
+ = replace_equiv_address (operands[4],
+ gen_rtx_PLUS (SImode,
+ operands[7], operands[8]));
+})
;; Another spotted bad code:
;; move rx,ry
;; move [ry],ry
+;; No stable test-case.
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=r")
- (match_operand:SI 1 "register_operand" "r"))
- (set (match_operand 2 "register_operand" "=r")
- (mem (match_dup 0)))]
+(define_peephole2 ; movei (peephole casesi+42)
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "register_operand" ""))
+ (set (match_operand 2 "register_operand" "")
+ (match_operator 3 "cris_mem_op" [(match_dup 0)]))]
"REGNO (operands[0]) == REGNO (operands[2])
&& GET_MODE_SIZE (GET_MODE (operands[2])) <= UNITS_PER_WORD"
- "move.%s2 [%1],%0"
- [(set_attr "slottable" "yes")])
+ [(set (match_dup 2) (match_dup 4))]
+ "operands[4] = replace_equiv_address (operands[3], operands[1]);")
-;; And a simple variant with extended operand.
-
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=r")
- (match_operand:SI 1 "register_operand" "r"))
- (set (match_operand 2 "register_operand" "=r")
- (match_operator 3 "cris_extend_operator" [(mem (match_dup 0))]))]
- "REGNO (operands[0]) == REGNO (operands[2])
- && GET_MODE_SIZE (GET_MODE (operands[2])) <= UNITS_PER_WORD"
- "mov%e3.%m3 [%1],%0"
- [(set_attr "slottable" "yes")])
-\f
-;; Here are all peepholes that have a saved testcase.
-;; Do not add new peepholes without testcases.
-
-;; peep-1:
;; move.d [r10+16],r9
;; and.d r12,r9
;; change to
;; register pressure.
;; Note that adding the noncommutative variant did not show any matches
;; in ipps and cc1, so it's not here.
+;; No stable test-case.
-(define_peephole
- [(set (match_operand 0 "register_operand" "=r,r,r,r")
- (mem (plus:SI
- (match_operand:SI 1 "cris_bdap_biap_operand" "r,r>Rn,r,r>Rn")
- (match_operand:SI 2 "cris_bdap_biap_operand" "r>Rn,r,r>Rn,r"))))
+(define_peephole2 ; op3 (peephole casesi+44)
+ [(set (match_operand 0 "register_operand" "")
+ (match_operator
+ 6 "cris_mem_op"
+ [(plus:SI
+ (match_operand:SI 1 "cris_bdap_biap_operand" "")
+ (match_operand:SI 2 "cris_bdap_biap_operand" ""))]))
(set (match_dup 0)
- (match_operator 5 "cris_commutative_orth_op"
- [(match_operand 3 "register_operand" "0,0,r,r")
- (match_operand 4 "register_operand" "r,r,0,0")]))]
+ (match_operator
+ 5 "cris_commutative_orth_op"
+ [(match_operand 3 "register_operand" "")
+ (match_operand 4 "register_operand" "")]))]
"(rtx_equal_p (operands[3], operands[0])
|| rtx_equal_p (operands[4], operands[0]))
&& ! rtx_equal_p (operands[3], operands[4])
&& (REG_S_P (operands[1]) || REG_S_P (operands[2]))
&& GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD"
- "@
- %x5.%s0 [%1%S2],%4,%0
- %x5.%s0 [%2%S1],%4,%0
- %x5.%s0 [%1%S2],%3,%0
- %x5.%s0 [%2%S1],%3,%0")
+ [(set (match_dup 0) (match_op_dup 5 [(match_dup 7) (match_dup 6)]))]
+ "operands[7]
+ = rtx_equal_p (operands[3], operands[0]) ? operands[4] : operands[3];")
-;; peep-2:
;; I cannot tell GCC (2.1, 2.7.2) how to correctly reload an instruction
;; that looks like
;; and.b some_byte,const,reg_32
;; move.b some_byte,reg_32
;; and.d const,reg_32
;; Fix it here.
+;; Testcases: gcc.dg/cris-peep2-andu1.c gcc.dg/cris-peep2-andu2.c
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=r")
- (match_operand:SI 1 "nonimmediate_operand" "rm"))
- (set (match_operand:SI 2 "register_operand" "=0")
+(define_peephole2 ; andu (casesi+45)
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "nonimmediate_operand" ""))
+ (set (match_operand:SI 2 "register_operand" "")
(and:SI (match_dup 0)
- (match_operand:SI 3 "const_int_operand" "n")))]
-
+ (match_operand:SI 3 "const_int_operand" "")))]
;; Since the size of the memory access could be made different here,
;; don't do this for a mem-volatile access.
-
"REGNO (operands[2]) == REGNO (operands[0])
&& INTVAL (operands[3]) <= 65535 && INTVAL (operands[3]) >= 0
&& ! CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'I')
&& (GET_CODE (operands[1]) != MEM || ! MEM_VOLATILE_P (operands[1]))"
- "*
-{
- if (CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'O'))
- return \"movu.%z3 %1,%0\;andq %b3,%0\";
-
- cc_status.flags |= CC_NOT_NEGATIVE;
-
- return \"movu.%z3 %1,%0\;and.%z3 %3,%0\";
-}")
-
-;; peep-3
-
-(define_peephole
- [(set (match_operand 0 "register_operand" "=r")
- (match_operand 1 "nonimmediate_operand" "rm"))
- (set (match_operand:SI 2 "register_operand" "=r")
- (and:SI (subreg:SI (match_dup 0) 0)
- (match_operand 3 "const_int_operand" "n")))]
-
- ;; Since the size of the memory access could be made different here,
- ;; don't do this for a mem-volatile access.
-
- "REGNO (operands[0]) == REGNO (operands[2])
- && INTVAL (operands[3]) > 0
- && INTVAL (operands[3]) <= 65535
- && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'I')
- && (GET_CODE (operands[1]) != MEM || ! MEM_VOLATILE_P (operands[1]))"
- "*
+ ;; FIXME: CC0 valid except for M (i.e. CC_NOT_NEGATIVE).
+ [(set (match_dup 0) (match_dup 4))
+ (set (match_dup 5) (match_dup 6))]
{
- if (CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'O'))
- return \"movu.%z3 %1,%0\;andq %b3,%0\";
-
- cc_status.flags |= CC_NOT_NEGATIVE;
-
- return \"movu.%z3 %1,%0\;and.%z3 %3,%0\";
-}")
+ enum machine_mode zmode = INTVAL (operands[3]) <= 255 ? QImode : HImode;
+ enum machine_mode amode
+ = CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'O') ? SImode : zmode;
+ rtx op1
+ = (REG_S_P (operands[1])
+ ? gen_rtx_REG (zmode, REGNO (operands[1]))
+ : adjust_address (operands[1], zmode, 0));
+ operands[4]
+ = gen_rtx_ZERO_EXTEND (SImode, op1);
+ operands[5] = gen_rtx_REG (amode, REGNO (operands[0]));
+ operands[6]
+ = gen_rtx_AND (amode, gen_rtx_REG (amode, REGNO (operands[0])),
+ GEN_INT (trunc_int_for_mode (INTVAL (operands[3]),
+ amode == SImode
+ ? QImode : amode)));
+})
\f
;; Local variables:
;; mode:emacs-lisp