summaryrefslogtreecommitdiff
path: root/gcc/rtlanal.c
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2000-09-29 11:24:13 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2000-09-29 11:24:13 +0000
commit6531eca959da0a7e2999f602420911093844e742 (patch)
treedaf24fe6a604f9c91a67080db41f6d3f1e17db76 /gcc/rtlanal.c
parent15bb264be412ea9e9a9875d4dbe37408bf0e4fe7 (diff)
downloadgcc-6531eca959da0a7e2999f602420911093844e742.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@36664 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/rtlanal.c')
-rw-r--r--gcc/rtlanal.c99
1 files changed, 72 insertions, 27 deletions
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index c19b3f5fa97..0d922c66c43 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;