diff options
author | Jan Hubicka <hubicka@gcc.gnu.org> | 2000-09-29 11:24:13 +0000 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2000-09-29 11:24:13 +0000 |
commit | b1cdafbb6c7bef4c21922ae2ce25b64445dc49cc (patch) | |
tree | daf24fe6a604f9c91a67080db41f6d3f1e17db76 /gcc | |
parent | 073427934aba95f673cbd8578ad36ac3d6055b05 (diff) | |
download | gcc-b1cdafbb6c7bef4c21922ae2ce25b64445dc49cc.zip gcc-b1cdafbb6c7bef4c21922ae2ce25b64445dc49cc.tar.gz gcc-b1cdafbb6c7bef4c21922ae2ce25b64445dc49cc.tar.bz2 |
recog.c (recog_memoized): Rename to recog_memoized_1.
* recog.c (recog_memoized): Rename to recog_memoized_1.
* recog.h (recog_memoized): Rename to recog_memoized_1.
(recog_memoized): New macro.
* rtl.h (single_set): Rename to single_set_1
(single_set): New macro.
* rtlanal.c (single_set): Rename to single_set_1; expect clobbers
to be last.
* i386.md (strmovsi_1, strmovhi_1 strmovqi_1):
Do not use match_dup of input operands at outputs.
Use register_operand for memory expression.
(rep_movsi): Put use last, canonicalize.
Use register_operand for memory expression.
(rep_movqi): Put use last.
Use register_operand for memory expression.
(strsetsi_1, strset_hi_1, strsetqi_1): Do not use match_dup
of input operands at outputs. Use register_operand for memory
expression.
(rep_stossi): Put use last; canonicalize; fix match_dup in
the address expression
(rep_stosqi): Likewise.
(memcmp expander): Update calls.
(cmpstrsi_nz_1, cmpstrsi_1, strlensi_1): Avoid match_dups in
the clobbers.
* i386.md (fp_jcc_3, fp_jcc_4, jp_fcc_5): if_then_else operand is
VOIDmode.
(fp_jcc_4, fp_jcc_3): Refuse unordered comparisons.
From-SVN: r36664
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/i386/i386-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 3 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 116 | ||||
-rw-r--r-- | gcc/recog.c | 2 | ||||
-rw-r--r-- | gcc/rtl.h | 8 | ||||
-rw-r--r-- | gcc/rtlanal.c | 99 |
6 files changed, 137 insertions, 92 deletions
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 263f526..fef5c52 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -125,6 +125,7 @@ extern int ix86_adjust_cost PARAMS ((rtx, rtx, rtx, int)); extern void ix86_sched_init PARAMS ((FILE *, int)); extern int ix86_sched_reorder PARAMS ((FILE *, int, rtx *, int, int)); extern int ix86_variable_issue PARAMS ((FILE *, int, rtx, int)); +extern enum machine_mode ix86_fp_compare_mode PARAMS ((enum rtx_code)); #ifdef TREE_CODE extern void init_cumulative_args PARAMS ((CUMULATIVE_ARGS *, tree, rtx)); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index efc0eaa..5521ea2 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -388,7 +388,6 @@ static void put_condition_code PARAMS ((enum rtx_code, enum machine_mode, int, int, FILE *)); static enum rtx_code unsigned_comparison PARAMS ((enum rtx_code code)); static rtx ix86_expand_int_compare PARAMS ((enum rtx_code, rtx, rtx)); -static enum machine_mode ix86_fp_compare_mode PARAMS ((enum rtx_code)); static enum rtx_code ix86_prepare_fp_compare_args PARAMS ((enum rtx_code, rtx *, rtx *)); static rtx gen_push PARAMS ((rtx)); @@ -4635,7 +4634,7 @@ ix86_expand_int_compare (code, op0, op1) /* Figure out whether to use ordered or unordered fp comparisons. Return the appropriate mode to use. */ -static enum machine_mode +enum machine_mode ix86_fp_compare_mode (code) enum rtx_code code; { diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index a855508..db8be56 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -8539,7 +8539,7 @@ (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 "" "")) @@ -8550,12 +8550,14 @@ "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) @@ -8566,7 +8568,9 @@ "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" @@ -10003,10 +10007,10 @@ [(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" @@ -10019,10 +10023,10 @@ [(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" @@ -10035,10 +10039,10 @@ [(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" @@ -10047,21 +10051,18 @@ (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" @@ -10072,13 +10073,14 @@ (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" @@ -10307,7 +10309,7 @@ [(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" @@ -10320,7 +10322,7 @@ [(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" @@ -10333,7 +10335,7 @@ [(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" @@ -10342,19 +10344,16 @@ (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" @@ -10365,12 +10364,13 @@ (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" @@ -10413,12 +10413,14 @@ 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); @@ -10448,21 +10450,17 @@ ;; 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") @@ -10473,17 +10471,17 @@ (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") @@ -10547,25 +10545,21 @@ 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" diff --git a/gcc/recog.c b/gcc/recog.c index f1d5dee..248f8d8 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -112,7 +112,7 @@ init_recog () through this one. (The only exception is in combine.c.) */ int -recog_memoized (insn) +recog_memoized_1 (insn) rtx insn; { if (INSN_CODE (insn) < 0) @@ -1329,6 +1329,12 @@ extern void set_unique_reg_note PARAMS ((rtx, enum reg_note, rtx)); /* Functions in rtlanal.c */ +/* Single set is implemented as macro for performance reasons. */ +#define single_set(I) (INSN_P (I) \ + ? (GET_CODE (PATTERN (I)) == SET \ + ? PATTERN (I) : single_set_1 (I)) \ + : NULL_RTX) + extern int rtx_unstable_p PARAMS ((rtx)); extern int rtx_varies_p PARAMS ((rtx)); extern int rtx_addr_varies_p PARAMS ((rtx)); @@ -1347,7 +1353,7 @@ extern int no_jumps_between_p PARAMS ((rtx, rtx)); extern int modified_in_p PARAMS ((rtx, rtx)); extern int insn_dependent_p PARAMS ((rtx, rtx)); extern int reg_set_p PARAMS ((rtx, rtx)); -extern rtx single_set PARAMS ((rtx)); +extern rtx single_set_1 PARAMS ((rtx)); extern int multiple_sets PARAMS ((rtx)); extern rtx find_last_value PARAMS ((rtx, rtx *, rtx, int)); extern int refers_to_regno_p PARAMS ((unsigned int, unsigned int, diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index c19b3f5..0d922c6 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -842,46 +842,91 @@ insn_dependent_p_1 (x, pat, data) 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; |