*** empty log message ***
authorRichard Kenner <kenner@gcc.gnu.org>
Sun, 28 Jun 1992 11:20:11 +0000 (07:20 -0400)
committerRichard Kenner <kenner@gcc.gnu.org>
Sun, 28 Jun 1992 11:20:11 +0000 (07:20 -0400)
From-SVN: r1320

gcc/expr.c
gcc/toplev.c

index 663a58f1a3a075973cf4953b2894b3a3d8da08c3..5da6892213f9a2cb479e6b78b097045431a2c6b9 100644 (file)
@@ -102,6 +102,13 @@ static void do_jump_by_parts_equality ();
 static void do_jump_by_parts_equality_rtx ();
 static void do_jump_by_parts_greater ();
 
+/* Record for each mode whether we can move a register directly to or
+   from an object of that mode in memory.  If we can't, we won't try
+   to use that mode directly when accessing a field of that mode.  */
+
+static char direct_load[NUM_MACHINE_MODES];
+static char direct_store[NUM_MACHINE_MODES];
+
 /* MOVE_RATIO is the number of move instructions that is better than
    a block move.  */
 
@@ -121,6 +128,52 @@ static void do_jump_by_parts_greater ();
 #define SLOW_UNALIGNED_ACCESS 0
 #endif
 \f
+/* This is run once per compilation to set up which modes can be used
+   directly in memory.  */
+
+void
+init_expr_once ()
+{
+  rtx insn, pat;
+  enum machine_mode mode;
+  rtx mem = gen_rtx (MEM, VOIDmode, stack_pointer_rtx);
+
+  start_sequence ();
+  insn = emit_insn (gen_rtx (SET, 0, 0));
+  pat = PATTERN (insn);
+
+  for (mode = VOIDmode; (int) mode < NUM_MACHINE_MODES;
+       mode = (enum machine_mode) ((int) mode + 1))
+    {
+      int regno;
+      rtx reg;
+      int num_clobbers;
+
+      direct_load[(int) mode] = direct_store[(int) mode] = 0;
+      PUT_MODE (mem, mode);
+
+      /* Find a register that can be used in this mode, if any.  */
+      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+       if (HARD_REGNO_MODE_OK (regno, mode))
+         break;
+
+      if (regno == FIRST_PSEUDO_REGISTER)
+       continue;
+
+      reg = gen_rtx (REG, mode, regno);
+
+      SET_SRC (pat) = mem;
+      SET_DEST (pat) = reg;
+      direct_load[(int) mode] = (recog (pat, insn, &num_clobbers)) >= 0;
+
+      SET_SRC (pat) = reg;
+      SET_DEST (pat) = mem;
+      direct_store[(int) mode] = (recog (pat, insn, &num_clobbers)) >= 0;
+    }
+
+  end_sequence ();
+}
+      
 /* This is run at the start of compiling a function.  */
 
 void
@@ -635,6 +688,7 @@ convert_move (to, from, unsignedp)
                                GET_MODE_BITSIZE (from_mode))
       && ((GET_CODE (from) == MEM
           && ! MEM_VOLATILE_P (from)
+          && direct_load[(int) to_mode]
           && ! mode_dependent_address_p (XEXP (from, 0)))
          || GET_CODE (from) == REG
          || GET_CODE (from) == SUBREG))
@@ -811,6 +865,7 @@ convert_to_mode (mode, x, unsignedp)
          && (GET_CODE (x) == CONST_DOUBLE
              || (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (x))
                  && ((GET_CODE (x) == MEM && ! MEM_VOLATILE_P (x))
+                     && direct_load[(int) mode]
                      || GET_CODE (x) == REG)))))
     return gen_lowpart (mode, x);
 
@@ -2496,7 +2551,9 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode,
      is a bit field, we cannot use addressing to access it.
      Use bit-field techniques or SUBREG to store in it.  */
 
-  if (mode == VOIDmode || GET_CODE (target) == REG
+  if (mode == VOIDmode
+      || (mode != BLKmode && ! direct_store[(int) mode])
+      || GET_CODE (target) == REG
       || GET_CODE (target) == SUBREG)
     {
       rtx temp = expand_expr (exp, 0, VOIDmode, 0);
@@ -3587,6 +3644,7 @@ expand_expr (exp, target, tmode, modifier)
          }
 
        if (mode1 == VOIDmode
+           || (mode1 != BLKmode && ! direct_load[(int) mode1])
            || GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
          {
            /* In cases where an aligned union has an unaligned object
index ab51d2f09c2dbf01e905b911fcf0333757f1b795..5c6dae117790aa176752b8744ba1549723767385 100644 (file)
@@ -1380,6 +1380,7 @@ compile_file (name)
   init_optabs ();
   init_stmt ();
   init_expmed ();
+  init_expr_once ();
   init_loop ();
   init_reload ();