OSDN Git Service

* config/alpha/alpha.c (alpha_split_tfmode_pair): Rename into
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 18 Jan 2006 11:20:51 +0000 (11:20 +0000)
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 18 Jan 2006 11:20:51 +0000 (11:20 +0000)
alpha_split_tmode_pair.  Add 'mode' and 'fixup_overlap' arguments.
Test against the appropriate null constant for the mode.
If 'fixup_overlap' is true, swap the operands if they overlap.
(alpha_split_tfmode_frobsign): Adjust call to alpha_split_tfmode_pair.
* config/alpha/alpha-protos.h (alpha_split_tfmode_pair): Rename into
alpha_split_tmode_pair and adjust for above change.
* config/alpha/alpha.md (movtf_internal): Adjust call to
alpha_split_tfmode_pair and rely on it to swap the operands.
(movti_internal): New insn and post-reload splitter.
(movti): New expander.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@109882 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/alpha/alpha-protos.h
gcc/config/alpha/alpha.c
gcc/config/alpha/alpha.md

index 3513cc2..8bb03f7 100644 (file)
@@ -1,3 +1,17 @@
+2006-01-18  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * config/alpha/alpha.c (alpha_split_tfmode_pair): Rename into
+       alpha_split_tmode_pair.  Add 'mode' and 'fixup_overlap' arguments.
+       Test against the appropriate null constant for the mode.
+       If 'fixup_overlap' is true, swap the operands if they overlap.
+       (alpha_split_tfmode_frobsign): Adjust call to alpha_split_tfmode_pair.
+       * config/alpha/alpha-protos.h (alpha_split_tfmode_pair): Rename into
+       alpha_split_tmode_pair and adjust for above change.
+       * config/alpha/alpha.md (movtf_internal): Adjust call to
+       alpha_split_tfmode_pair and rely on it to swap the operands.
+       (movti_internal): New insn and post-reload splitter.
+       (movti): New expander.
+
 2006-01-18  Philippe De Muyter  <phdm@macqel.be>
 
        * config/m68k/m68k.md (*addsi3_5200): Allow addq/subq to memory
index 00fc525..f099b4d 100644 (file)
@@ -64,7 +64,7 @@ extern bool alpha_expand_mov_nobwx (enum machine_mode, rtx *);
 extern void alpha_expand_movmisalign (enum machine_mode, rtx *);
 extern void alpha_emit_floatuns (rtx[]);
 extern rtx alpha_emit_conditional_move (rtx, enum machine_mode);
-extern void alpha_split_tfmode_pair (rtx[]);
+extern void alpha_split_tmode_pair (rtx[], enum machine_mode, bool);
 extern void alpha_split_tfmode_frobsign (rtx[], rtx (*)(rtx, rtx, rtx));
 extern void alpha_expand_unaligned_load (rtx, rtx, HOST_WIDE_INT,
                                         HOST_WIDE_INT, int);
index 244aa27..c684a4c 100644 (file)
@@ -3198,12 +3198,17 @@ alpha_emit_xfloating_cvt (enum rtx_code orig_code, rtx operands[])
                                               operands[1]));
 }
 
-/* Split a TFmode OP[1] into DImode OP[2,3] and likewise for
-   OP[0] into OP[0,1].  Naturally, output operand ordering is
-   little-endian.  */
-
+/* Split a TImode or TFmode move from OP[1] to OP[0] into a pair of
+   DImode moves from OP[2,3] to OP[0,1].  If FIXUP_OVERLAP is true,
+   guarantee that the sequence
+     set (OP[0] OP[2])
+     set (OP[1] OP[3])
+   is valid.  Naturally, output operand ordering is little-endian.
+   This is used by *movtf_internal and *movti_internal.  */
+  
 void
-alpha_split_tfmode_pair (rtx operands[4])
+alpha_split_tmode_pair (rtx operands[4], enum machine_mode mode,
+                       bool fixup_overlap)
 {
   switch (GET_CODE (operands[1]))
     {
@@ -3217,8 +3222,9 @@ alpha_split_tfmode_pair (rtx operands[4])
       operands[2] = adjust_address (operands[1], DImode, 0);
       break;
 
+    case CONST_INT:
     case CONST_DOUBLE:
-      gcc_assert (operands[1] == CONST0_RTX (TFmode));
+      gcc_assert (operands[1] == CONST0_RTX (mode));
       operands[2] = operands[3] = const0_rtx;
       break;
 
@@ -3241,6 +3247,13 @@ alpha_split_tfmode_pair (rtx operands[4])
     default:
       gcc_unreachable ();
     }
+
+  if (fixup_overlap && reg_overlap_mentioned_p (operands[0], operands[3]))
+    {
+      rtx tmp;
+      tmp = operands[0], operands[0] = operands[1], operands[1] = tmp;
+      tmp = operands[2], operands[2] = operands[3], operands[3] = tmp;
+    }
 }
 
 /* Implement negtf2 or abstf2.  Op0 is destination, op1 is source,
@@ -3254,7 +3267,7 @@ alpha_split_tfmode_frobsign (rtx operands[3], rtx (*operation) (rtx, rtx, rtx))
   rtx scratch;
   int move;
 
-  alpha_split_tfmode_pair (operands);
+  alpha_split_tmode_pair (operands, TFmode, false);
 
   /* Detect three flavors of operand overlap.  */
   move = 1;
index d9f9e09..2838499 100644 (file)
   [(set (match_dup 0) (match_dup 2))
    (set (match_dup 1) (match_dup 3))]
 {
-  alpha_split_tfmode_pair (operands);
-  if (reg_overlap_mentioned_p (operands[0], operands[3]))
-    {
-      rtx tmp;
-      tmp = operands[0], operands[0] = operands[1], operands[1] = tmp;
-      tmp = operands[2], operands[2] = operands[3], operands[3] = tmp;
-    }
+  alpha_split_tmode_pair (operands, TFmode, true); 
 })
 
 (define_expand "movsf"
     FAIL;
 })
 
+;; We need to prevent reload from splitting TImode moves, because it
+;; might decide to overwrite a pointer with the value it points to.
+;; In that case we have to do the loads in the appropriate order so
+;; that the pointer is not destroyed too early.
+
+(define_insn_and_split "*movti_internal"
+  [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o")
+        (match_operand:TI 1 "input_operand" "roJ,rJ"))]
+  "(register_operand (operands[0], TImode)
+    /* Prevent rematerialization of constants.  */
+    && ! CONSTANT_P (operands[1]))
+   || reg_or_0_operand (operands[1], TImode)"
+  "#"
+  "reload_completed"
+  [(set (match_dup 0) (match_dup 2))
+   (set (match_dup 1) (match_dup 3))]
+{
+  alpha_split_tmode_pair (operands, TImode, true);
+})
+
+(define_expand "movti"
+  [(set (match_operand:TI 0 "nonimmediate_operand" "")
+        (match_operand:TI 1 "general_operand" ""))]
+  ""
+{
+  if (GET_CODE (operands[0]) == MEM
+      && ! reg_or_0_operand (operands[1], TImode))
+    operands[1] = force_reg (TImode, operands[1]);
+
+  if (operands[1] == const0_rtx)
+    ;
+  /* We must put 64-bit constants in memory.  We could keep the
+     32-bit constants in TImode and rely on the splitter, but
+     this doesn't seem to be worth the pain.  */
+  else if (GET_CODE (operands[1]) == CONST_INT
+          || GET_CODE (operands[1]) == CONST_DOUBLE)
+    {
+      rtx in[2], out[2], target;
+
+      gcc_assert (!no_new_pseudos);
+
+      split_double (operands[1], &in[0], &in[1]);
+
+      if (in[0] == const0_rtx)
+       out[0] = const0_rtx;
+      else
+       {
+         out[0] = gen_reg_rtx (DImode);
+         emit_insn (gen_movdi (out[0], in[0]));
+       }
+
+      if (in[1] == const0_rtx)
+       out[1] = const0_rtx;
+      else
+       {
+         out[1] = gen_reg_rtx (DImode);
+         emit_insn (gen_movdi (out[1], in[1]));
+       }
+
+      if (GET_CODE (operands[0]) != REG)
+       target = gen_reg_rtx (TImode);
+      else
+       target = operands[0];
+
+      emit_insn (gen_movdi (gen_rtx_SUBREG (DImode, target, 0), out[0]));
+      emit_insn (gen_movdi (gen_rtx_SUBREG (DImode, target, 8), out[1]));
+
+      if (target != operands[0])
+       emit_insn (gen_rtx_SET (VOIDmode, operands[0], target));
+
+      DONE;
+    }
+})
+
 ;; These are the partial-word cases.
 ;;
 ;; First we have the code to load an aligned word.  Operand 0 is the register