(define_insn "*fp_jcc_3"
[(set (pc)
- (if_then_else (match_operator:CCFP 0 "comparison_operator"
+ (if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "f")
(match_operand 2 "nonimmediate_operand" "fm")])
(label_ref (match_operand 3 "" ""))
"TARGET_80387
&& (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode)
&& GET_MODE (operands[1]) == GET_MODE (operands[2])
- && !ix86_use_fcomi_compare (GET_CODE (operands[0]))"
+ && !ix86_use_fcomi_compare (GET_CODE (operands[0]))
+ && SELECT_CC_MODE (GET_CODE (operands[0]),
+ operands[1], operands[2]) == CCFPmode"
"#")
(define_insn "*fp_jcc_4"
[(set (pc)
- (if_then_else (match_operator:CCFP 0 "comparison_operator"
+ (if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "f")
(match_operand 2 "nonimmediate_operand" "fm")])
(pc)
"TARGET_80387
&& (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode)
&& GET_MODE (operands[1]) == GET_MODE (operands[2])
- && !ix86_use_fcomi_compare (GET_CODE (operands[0]))"
+ && !ix86_use_fcomi_compare (GET_CODE (operands[0]))
+ && SELECT_CC_MODE (GET_CODE (operands[0]),
+ operands[1], operands[2]) == CCFPmode"
"#")
(define_insn "*fp_jcc_5"
[(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
(mem:SI (match_operand:SI 3 "register_operand" "1")))
(set (match_operand:SI 0 "register_operand" "=D")
- (plus:SI (match_dup 0)
+ (plus:SI (match_dup 2)
(const_int 4)))
(set (match_operand:SI 1 "register_operand" "=S")
- (plus:SI (match_dup 1)
+ (plus:SI (match_dup 3)
(const_int 4)))
(use (reg:SI 19))]
"TARGET_SINGLE_STRINGOP || optimize_size"
[(set (mem:HI (match_operand:SI 2 "register_operand" "0"))
(mem:HI (match_operand:SI 3 "register_operand" "1")))
(set (match_operand:SI 0 "register_operand" "=D")
- (plus:SI (match_dup 0)
+ (plus:SI (match_dup 2)
(const_int 2)))
(set (match_operand:SI 1 "register_operand" "=S")
- (plus:SI (match_dup 1)
+ (plus:SI (match_dup 3)
(const_int 2)))
(use (reg:SI 19))]
"TARGET_SINGLE_STRINGOP || optimize_size"
[(set (mem:QI (match_operand:SI 2 "register_operand" "0"))
(mem:QI (match_operand:SI 3 "register_operand" "1")))
(set (match_operand:SI 0 "register_operand" "=D")
- (plus:SI (match_dup 0)
+ (plus:SI (match_dup 2)
(const_int 1)))
(set (match_operand:SI 1 "register_operand" "=S")
- (plus:SI (match_dup 1)
+ (plus:SI (match_dup 3)
(const_int 1)))
(use (reg:SI 19))]
"TARGET_SINGLE_STRINGOP || optimize_size"
(set_attr "memory" "both")
(set_attr "mode" "QI")])
-;; It might seem that operands 3 & 4 could use predicate register_operand.
-;; But strength reduction might offset the MEM expression. So we let
-;; reload put the address into %edi & %esi.
-
(define_insn "rep_movsi"
[(set (match_operand:SI 2 "register_operand" "=c") (const_int 0))
- (use (match_operand:SI 5 "register_operand" "2"))
(set (match_operand:SI 0 "register_operand" "=D")
- (plus:SI (match_operand:SI 3 "address_operand" "0")
- (ashift:SI (match_dup 5) (const_int 2))))
+ (plus:SI (ashift:SI (match_operand:SI 5 "register_operand" "2")
+ (const_int 2))
+ (match_operand:SI 3 "register_operand" "0")))
(set (match_operand:SI 1 "register_operand" "=S")
- (plus:SI (match_operand:SI 4 "address_operand" "1")
- (ashift:SI (match_dup 5) (const_int 2))))
+ (plus:SI (ashift:SI (match_dup 5) (const_int 2))
+ (match_operand:SI 4 "register_operand" "1")))
(set (mem:BLK (match_dup 3))
(mem:BLK (match_dup 4)))
+ (use (match_dup 5))
(use (reg:SI 19))]
""
"rep\;movsl|rep movsd"
(define_insn "rep_movqi"
[(set (match_operand:SI 2 "register_operand" "=c") (const_int 0))
- (use (match_operand:SI 5 "register_operand" "2"))
(set (match_operand:SI 0 "register_operand" "=D")
- (plus:SI (match_operand:SI 3 "address_operand" "0") (match_dup 5)))
+ (plus:SI (match_operand:SI 3 "register_operand" "0")
+ (match_operand:SI 5 "register_operand" "2")))
(set (match_operand:SI 1 "register_operand" "=S")
- (plus:SI (match_operand:SI 4 "address_operand" "1") (match_dup 5)))
+ (plus:SI (match_operand:SI 4 "register_operand" "1") (match_dup 5)))
(set (mem:BLK (match_dup 3))
(mem:BLK (match_dup 4)))
+ (use (match_dup 5))
(use (reg:SI 19))]
""
"rep\;movsb|rep movsb"
[(set (mem:SI (match_operand:SI 1 "register_operand" "0"))
(match_operand:SI 2 "register_operand" "a"))
(set (match_operand:SI 0 "register_operand" "=D")
- (plus:SI (match_dup 0)
+ (plus:SI (match_dup 1)
(const_int 4)))
(use (reg:SI 19))]
"TARGET_SINGLE_STRINGOP || optimize_size"
[(set (mem:HI (match_operand:SI 1 "register_operand" "0"))
(match_operand:HI 2 "register_operand" "a"))
(set (match_operand:SI 0 "register_operand" "=D")
- (plus:SI (match_dup 0)
+ (plus:SI (match_dup 1)
(const_int 2)))
(use (reg:SI 19))]
"TARGET_SINGLE_STRINGOP || optimize_size"
[(set (mem:QI (match_operand:SI 1 "register_operand" "0"))
(match_operand:QI 2 "register_operand" "a"))
(set (match_operand:SI 0 "register_operand" "=D")
- (plus:SI (match_dup 0)
+ (plus:SI (match_dup 1)
(const_int 1)))
(use (reg:SI 19))]
"TARGET_SINGLE_STRINGOP || optimize_size"
(set_attr "memory" "store")
(set_attr "mode" "QI")])
-;; It might seem that operand 0 could use predicate register_operand.
-;; But strength reduction might offset the MEM expression. So we let
-;; reload put the address into %edi.
-
(define_insn "rep_stossi"
[(set (match_operand:SI 1 "register_operand" "=c") (const_int 0))
- (use (match_operand:SI 2 "register_operand" "a"))
- (use (match_operand:SI 4 "register_operand" "1"))
(set (match_operand:SI 0 "register_operand" "=D")
- (plus:SI (match_operand:SI 3 "address_operand" "0")
- (ashift:SI (match_dup 3) (const_int 2))))
+ (plus:SI (ashift:SI (match_operand:SI 4 "register_operand" "1")
+ (const_int 2))
+ (match_operand:SI 3 "register_operand" "0")))
(set (mem:BLK (match_dup 3))
(const_int 0))
+ (use (match_operand:SI 2 "register_operand" "a"))
+ (use (match_dup 4))
(use (reg:SI 19))]
""
"rep\;stosl|rep stosd"
(define_insn "rep_stosqi"
[(set (match_operand:SI 1 "register_operand" "=c") (const_int 0))
- (use (match_operand:QI 2 "register_operand" "a"))
- (use (match_operand:SI 4 "register_operand" "1"))
(set (match_operand:SI 0 "register_operand" "=D")
- (plus:SI (match_operand:SI 3 "address_operand" "0") (match_dup 3)))
+ (plus:SI (match_operand:SI 3 "register_operand" "0")
+ (match_operand:SI 4 "register_operand" "1")))
(set (mem:BLK (match_dup 3))
(const_int 0))
+ (use (match_operand:QI 2 "register_operand" "a"))
+ (use (match_dup 4))
(use (reg:SI 19))]
""
"rep\;stosb|rep stosb"
emit_move_insn (operands[0], const0_rtx);
DONE;
}
- emit_insn (gen_cmpstrsi_nz_1 (addr1, addr2, countreg, align));
+ emit_insn (gen_cmpstrsi_nz_1 (addr1, addr2, countreg, align,
+ addr1, addr2, countreg));
}
else
{
emit_insn (gen_cmpsi_1 (countreg, countreg));
- emit_insn (gen_cmpstrsi_1 (addr1, addr2, countreg, align));
+ emit_insn (gen_cmpstrsi_1 (addr1, addr2, countreg, align,
+ addr1, addr2, countreg));
}
outlow = gen_lowpart (QImode, out);
;; memcmp recognizers. The `cmpsb' opcode does nothing if the count is
;; zero. Emit extra code to make sure that a zero-length compare is EQ.
-;;
-;; It might seem that operands 0 & 1 could use predicate register_operand.
-;; But strength reduction might offset the MEM expression. So we let
-;; reload put the address into %edi & %esi.
(define_insn "cmpstrsi_nz_1"
[(set (reg:CC 17)
- (compare:CC (mem:BLK (match_operand:SI 0 "address_operand" "S"))
- (mem:BLK (match_operand:SI 1 "address_operand" "D"))))
- (use (match_operand:SI 2 "register_operand" "c"))
+ (compare:CC (mem:BLK (match_operand:SI 4 "register_operand" "0"))
+ (mem:BLK (match_operand:SI 5 "register_operand" "1"))))
+ (use (match_operand:SI 6 "register_operand" "2"))
(use (match_operand:SI 3 "immediate_operand" "i"))
(use (reg:SI 19))
- (clobber (match_dup 0))
- (clobber (match_dup 1))
- (clobber (match_dup 2))]
+ (clobber (match_operand:SI 0 "register_operand" "=S"))
+ (clobber (match_operand:SI 1 "register_operand" "=D"))
+ (clobber (match_operand:SI 2 "register_operand" "=c"))]
""
"repz{\;| }cmpsb"
[(set_attr "type" "str")
(define_insn "cmpstrsi_1"
[(set (reg:CC 17)
- (if_then_else:CC (ne (match_operand:SI 2 "register_operand" "c")
+ (if_then_else:CC (ne (match_operand:SI 6 "register_operand" "2")
(const_int 0))
- (compare:SI (mem:BLK (match_operand:SI 0 "address_operand" "S"))
- (mem:BLK (match_operand:SI 1 "address_operand" "D")))
+ (compare:SI (mem:BLK (match_operand:SI 4 "register_operand" "0"))
+ (mem:BLK (match_operand:SI 5 "register_operand" "1")))
(const_int 0)))
(use (match_operand:SI 3 "immediate_operand" "i"))
(use (reg:CC 17))
(use (reg:SI 19))
- (clobber (match_dup 0))
- (clobber (match_dup 1))
- (clobber (match_dup 2))]
+ (clobber (match_operand:SI 0 "register_operand" "=S"))
+ (clobber (match_operand:SI 1 "register_operand" "=D"))
+ (clobber (match_operand:SI 2 "register_operand" "=c"))]
""
"repz{\;| }cmpsb"
[(set_attr "type" "str")
emit_insn (gen_cld ());
emit_insn (gen_strlensi_1 (scratch1, scratch3, eoschar,
- align, constm1_rtx));
+ align, constm1_rtx, scratch3));
emit_insn (gen_one_cmplsi2 (scratch2, scratch1));
emit_insn (gen_addsi3 (out, scratch2, constm1_rtx));
}
DONE;
}")
-;; It might seem that operands 0 & 1 could use predicate register_operand.
-;; But strength reduction might offset the MEM expression. So we let
-;; reload put the address into %edi.
-
(define_insn "strlensi_1"
[(set (match_operand:SI 0 "register_operand" "=&c")
- (unspec:SI [(mem:BLK (match_operand:SI 1 "address_operand" "D"))
+ (unspec:SI [(mem:BLK (match_operand:SI 5 "register_operand" "1"))
(match_operand:QI 2 "general_operand" "a")
(match_operand:SI 3 "immediate_operand" "i")
(match_operand:SI 4 "immediate_operand" "0")] 0))
(use (reg:SI 19))
- (clobber (match_dup 1))
+ (clobber (match_operand:SI 1 "register_operand" "=D"))
(clobber (reg:CC 17))]
""
"repnz{\;| }scasb"
will not be used, which we ignore. */
rtx
-single_set (insn)
+single_set_1 (insn)
rtx insn;
{
rtx set;
+ rtx pat = PATTERN (insn);
int i;
- if (! INSN_P (insn))
- return 0;
-
- if (GET_CODE (PATTERN (insn)) == SET)
- return PATTERN (insn);
-
- else if (GET_CODE (PATTERN (insn)) == PARALLEL)
+ if (GET_CODE (pat) == PARALLEL)
{
- for (i = 0, set = 0; i < XVECLEN (PATTERN (insn), 0); i++)
+ rtx x, sub;
+ /* This part is is performance critical for targets that use a lot of
+ parallels, such as i386. We want to accept as single set
+ instructions even an instructions with multiple sets where only
+ one has live result, but we attempt to delay this tests only for
+ multiple set instructions to reduce amount of calls to
+ find_reg_note and side_effects_p.
+
+ We expect the "common" instruction to be parallel with first SET
+ followed by the clobbers. So first we get the set, then look
+ if it is followed by USE or CLOBBER. If so, we just return expect
+ no SETs after these. When SET is followed by another SET, we
+ continue by the clomplex loop trought all members of PARALLEL.
+ */
+#ifdef ENABLE_CHECKING
+ if (XVECLEN (pat, 0) < 2)
+ abort ();
+#endif
+ set = XVECEXP (pat, 0, 0);
+ switch (GET_CODE (set))
{
- rtx sub = XVECEXP (PATTERN (insn), 0, i);
-
- switch (GET_CODE (sub))
+#ifdef ENABLE_CHECKING
+ case USE:
+ case CLOBBER:
+ /* Instruction should not consist only from USEs and CLOBBERS,
+ since then gcc is allowed to remove it entirely. In case
+ something else is present, it should be first in the pattern. */
+ abort();
+#endif
+ case SET:
+ break;
+ default:
+ return NULL_RTX;
+ }
+ x = XVECEXP (pat, 0, 1);
+ switch (GET_CODE (x))
+ {
+ case USE:
+ case CLOBBER:
+#ifdef ENABLE_CHECKING
+ /* The USEs and CLOBBERs should always come last in the pattern. */
+ for (i = XVECLEN (pat, 0) - 1; i > 1; i--)
+ if (GET_CODE (XVECEXP (pat, 0, i)) != USE
+ && GET_CODE (XVECEXP (pat, 0, i)) != CLOBBER)
+ abort();
+#endif
+ return set;
+ case SET:
+ /* Multiple set insns - we are off the critical path now. */
+ for (i = XVECLEN (pat, 0) - 1; i > 0; i--)
{
- case USE:
- case CLOBBER:
- break;
-
- case SET:
- if (! find_reg_note (insn, REG_UNUSED, SET_DEST (sub))
- || side_effects_p (sub))
+ sub = XVECEXP (pat, 0, i);
+ switch GET_CODE (sub)
{
- if (set)
- return 0;
- else
+ case USE:
+ case CLOBBER:
+ break;
+
+ case SET:
+ if (!set
+ || (find_reg_note (insn, REG_UNUSED, SET_DEST (set))
+ && side_effects_p (set)))
set = sub;
- }
- break;
+ else if (! find_reg_note (insn, REG_UNUSED, SET_DEST (sub))
+ || side_effects_p (sub))
+ return NULL_RTX;
+ break;
- default:
- return 0;
+ default:
+ return NULL_RTX;
+ }
}
+ return set;
+ default:
+ return NULL_RTX;
}
- return set;
}
return 0;