aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>1992-08-14 07:40:16 -0400
committerRichard Kenner <kenner@gcc.gnu.org>1992-08-14 07:40:16 -0400
commit266007a7d6985c467758bbb61b3b23667de075cf (patch)
treee3384ae57db51caa4f72b6aa04dfee65fec64cd9 /gcc
parentefb07da787b7220a320f7f93b752f82fc34cef0b (diff)
downloadgcc-266007a7d6985c467758bbb61b3b23667de075cf.zip
gcc-266007a7d6985c467758bbb61b3b23667de075cf.tar.gz
gcc-266007a7d6985c467758bbb61b3b23667de075cf.tar.bz2
(movstr_optab): New variable.
(init_expr_once): Initialize it. (emit_block_move): Rework code that generates movstrxx insns to check predicates and use an optab. From-SVN: r1827
Diffstat (limited to 'gcc')
-rw-r--r--gcc/expr.c105
1 files changed, 57 insertions, 48 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index ef537e9..1959bf9 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -113,7 +113,7 @@ static char direct_store[NUM_MACHINE_MODES];
a block move. */
#ifndef MOVE_RATIO
-#if defined (HAVE_movstrqi) || defined (HAVE_movstrhi) || defined (HAVE_movstrsi) || defined (HAVE_movstrdi)
+#if defined (HAVE_movstrqi) || defined (HAVE_movstrhi) || defined (HAVE_movstrsi) || defined (HAVE_movstrdi) || defined (HAVE_movstrti)
#define MOVE_RATIO 2
#else
/* A value of around 6 would minimize code size; infinity would minimize
@@ -122,6 +122,9 @@ static char direct_store[NUM_MACHINE_MODES];
#endif
#endif
+/* This array records the insn_code of insns to perform block moves. */
+static enum insn_code movstr_optab[NUM_MACHINE_MODES];
+
/* SLOW_UNALIGNED_ACCESS is non-zero if unaligned accesses are very slow. */
#ifndef SLOW_UNALIGNED_ACCESS
@@ -129,7 +132,7 @@ static char direct_store[NUM_MACHINE_MODES];
#endif
/* This is run once per compilation to set up which modes can be used
- directly in memory. */
+ directly in memory and to initialize the block move optab. */
void
init_expr_once ()
@@ -169,9 +172,32 @@ init_expr_once ()
SET_SRC (pat) = reg;
SET_DEST (pat) = mem;
direct_store[(int) mode] = (recog (pat, insn, &num_clobbers)) >= 0;
+
+ movstr_optab[(int) mode] = CODE_FOR_nothing;
}
end_sequence ();
+
+#ifdef HAVE_movstrqi
+ if (HAVE_movstrqi)
+ movstr_optab[(int) QImode] = CODE_FOR_movstrqi;
+#endif
+#ifdef HAVE_movstrhi
+ if (HAVE_movstrhi)
+ movstr_optab[(int) HImode] = CODE_FOR_movstrhi;
+#endif
+#ifdef HAVE_movstrsi
+ if (HAVE_movstrsi)
+ movstr_optab[(int) SImode] = CODE_FOR_movstrsi;
+#endif
+#ifdef HAVE_movstrdi
+ if (HAVE_movstrdi)
+ movstr_optab[(int) DImode] = CODE_FOR_movstrdi;
+#endif
+#ifdef HAVE_movstrti
+ if (HAVE_movstrti)
+ movstr_optab[(int) TImode] = CODE_FOR_movstrti;
+#endif
}
/* This is run at the start of compiling a function. */
@@ -1142,56 +1168,39 @@ emit_block_move (x, y, size, align)
/* Try the most limited insn first, because there's no point
including more than one in the machine description unless
the more limited one has some advantage. */
-#ifdef HAVE_movstrqi
- if (HAVE_movstrqi
- && GET_CODE (size) == CONST_INT
- && ((unsigned) INTVAL (size)
- < (1 << (GET_MODE_BITSIZE (QImode) - 1))))
- {
- rtx insn = gen_movstrqi (x, y, size, GEN_INT (align));
- if (insn)
- {
- emit_insn (insn);
- return;
- }
- }
-#endif
-#ifdef HAVE_movstrhi
- if (HAVE_movstrhi
- && GET_CODE (size) == CONST_INT
- && ((unsigned) INTVAL (size)
- < (1 << (GET_MODE_BITSIZE (HImode) - 1))))
- {
- rtx insn = gen_movstrhi (x, y, size, GEN_INT (align));
- if (insn)
- {
- emit_insn (insn);
- return;
- }
- }
-#endif
-#ifdef HAVE_movstrsi
- if (HAVE_movstrsi)
- {
- rtx insn = gen_movstrsi (x, y, size, GEN_INT (align));
- if (insn)
- {
- emit_insn (insn);
- return;
- }
- }
-#endif
-#ifdef HAVE_movstrdi
- if (HAVE_movstrdi)
+
+ enum machine_mode mode;
+
+ for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
+ mode = GET_MODE_WIDER_MODE (mode))
{
- rtx insn = gen_movstrdi (x, y, size, GEN_INT (align));
- if (insn)
+ enum insn_code code = movstr_optab[(int) mode];
+ rtx opalign = GEN_INT (align);
+
+ if (code != CODE_FOR_nothing
+ && GET_MODE_BITSIZE (mode) < HOST_BITS_PER_WIDE_INT
+ && (unsigned) INTVAL (size) <= GET_MODE_MASK (mode)
+ && (*insn_operand_predicate[(int) code][0]) (x, Pmode)
+ && (*insn_operand_predicate[(int) code][1]) (y, Pmode)
+ && (*insn_operand_predicate[(int) code][3]) (opalign, VOIDmode))
{
- emit_insn (insn);
- return;
+ rtx op2 = size;
+ rtx last = get_last_insn ();
+ rtx pat;
+
+ if (! (*insn_operand_predicate[(int) code][2]) (op2, mode))
+ op2 = copy_to_mode_reg (mode, op2);
+
+ pat = GEN_FCN ((int) code) (x, y, op2, opalign);
+ if (pat)
+ {
+ emit_insn (pat);
+ return;
+ }
+ else
+ delete_insns_since (last);
}
}
-#endif
#ifdef TARGET_MEM_FUNCTIONS
emit_library_call (memcpy_libfunc, 1,