OSDN Git Service

* expr.c (emit_move_insn_1): Split push of complex value when
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 14 Mar 2001 15:38:55 +0000 (15:38 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 14 Mar 2001 15:38:55 +0000 (15:38 +0000)
no suitable push instruction exist.

* i386.md (QImode move/add/shift patterns): Use ANY_QI_REG_P
instead of QI_REG_P.

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

gcc/ChangeLog
gcc/config/i386/i386.h
gcc/config/i386/i386.md
gcc/expr.c

index d723d45..54031ae 100644 (file)
@@ -1,3 +1,11 @@
+Wed Mar 14 16:36:25 CET 2001  Jan Hubicka  <jh@suse.cz>
+
+       * expr.c (emit_move_insn_1):  Split push of complex value when
+       no suitable push instruction exist.
+
+       * i386.md (QImode move/add/shift patterns): Use ANY_QI_REG_P
+       instead of QI_REG_P.
+
 Tue Mar 13 22:22:04 2001  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
 
        * alias.c (handled_component_p, can_address_p): New functions.
index 58f622b..df06a2f 100644 (file)
@@ -1138,7 +1138,7 @@ enum reg_class
   ((n) < 8 || REX_INT_REGNO_P (n))
 
 #define GENERAL_REG_P(X) \
-  (REG_P (X) && GENERAL_REG_REGNO_P (X))
+  (REG_P (X) && GENERAL_REGNO_P (X))
 
 #define ANY_QI_REG_P(X) (TARGET_64BIT ? GENERAL_REG_P(X) : QI_REG_P (X))
 
index 5f6cef6..c700f23 100644 (file)
   switch (get_attr_type (insn))
     {
     case TYPE_IMOVX:
-      if (!QI_REG_P (operands[1]) && GET_CODE (operands[1]) != MEM)
+      if (!ANY_QI_REG_P (operands[1]) && GET_CODE (operands[1]) != MEM)
        abort ();
       return \"movz{bl|x}\\t{%1, %k0|%k0, %1}\";
     default:
    (clobber (reg:CC 17))]
   "reload_completed 
    && (!TARGET_ZERO_EXTEND_WITH_AND || optimize_size)
-   && (!REG_P (operands[1]) || QI_REG_P (operands[1]))"
+   && (!REG_P (operands[1]) || ANY_QI_REG_P (operands[1]))"
   [(set (match_operand:HI 0 "register_operand" "")
        (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))])
 
        (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))
    (clobber (reg:CC 17))]
   "reload_completed
-   && QI_REG_P (operands[0])
+   && ANY_QI_REG_P (operands[0])
    && (TARGET_ZERO_EXTEND_WITH_AND && !optimize_size)
    && !reg_overlap_mentioned_p (operands[0], operands[1])"
   [(set (match_dup 0) (const_int 0))
    (clobber (reg:CC 17))]
   "reload_completed 
    && (!TARGET_ZERO_EXTEND_WITH_AND || optimize_size)
-   && (!REG_P (operands[1]) || QI_REG_P (operands[1]))"
+   && (!REG_P (operands[1]) || ANY_QI_REG_P (operands[1]))"
   [(set (match_dup 0)
        (zero_extend:SI (match_dup 1)))])
 
        (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))
    (clobber (reg:CC 17))]
   "reload_completed
-   && QI_REG_P (operands[0])
-   && (QI_REG_P (operands[1]) || GET_CODE (operands[1]) == MEM)
+   && ANY_QI_REG_P (operands[0])
+   && (ANY_QI_REG_P (operands[1]) || GET_CODE (operands[1]) == MEM)
    && (TARGET_ZERO_EXTEND_WITH_AND && !optimize_size)
    && !reg_overlap_mentioned_p (operands[0], operands[1])"
   [(set (match_dup 0) (const_int 0))
     case TYPE_ALU:
       if (operands[2] != const1_rtx)
        abort ();
-      if (NON_QI_REG_P (operands[1]))
+      if (REG_P (operands[1]) && !ANY_QI_REG_P (operands[1]))
         return \"add{l}\\t{%k0, %k0|%k0, %k0}\";
       else
         return \"add{b}\\t{%0, %0|%0, %0}\";
     case TYPE_ALU:
       if (operands[2] != const1_rtx)
        abort ();
-      if (NON_QI_REG_P (operands[1]))
+      if (REG_P (operands[1]) && !ANY_QI_REG_P (operands[1]))
         return \"add{l}\\t{%k0, %k0|%k0, %k0}\";
       else
         return \"add{b}\\t{%0, %0|%0, %0}\";
     default:
       if (REG_P (operands[2]))
        {
-          if (NON_QI_REG_P (operands[1]))
+         if (get_attr_mode (insn) == MODE_SI)
            return \"sal{l}\\t{%b2, %k0|%k0, %b2}\";
          else
            return \"sal{b}\\t{%b2, %0|%0, %b2}\";
               && INTVAL (operands[2]) == 1
               && (TARGET_PENTIUM || TARGET_PENTIUMPRO))
        {
-          if (NON_QI_REG_P (operands[1]))
+         if (get_attr_mode (insn) == MODE_SI)
            return \"sal{l}\\t%0\";
          else
            return \"sal{b}\\t%0\";
        }
       else
        {
-          if (NON_QI_REG_P (operands[1]))
+         if (get_attr_mode (insn) == MODE_SI)
            return \"sal{l}\\t{%2, %k0|%k0, %2}\";
          else
            return \"sal{b}\\t{%2, %0|%0, %2}\";
index 382bb23..44900a6 100644 (file)
@@ -2786,12 +2786,55 @@ emit_move_insn_1 (x, y)
       /* Don't split destination if it is a stack push.  */
       int stack = push_operand (x, GET_MODE (x));
 
+      /* In case we output to the stack, but the size is smaller machine can
+        push exactly, we need to use move instructions.  */
+      if (stack
+         && PUSH_ROUNDING (GET_MODE_SIZE (submode)) != GET_MODE_SIZE (submode))
+       {
+         rtx temp;
+         int offset1, offset2;
+
+         /* Do not use anti_adjust_stack, since we don't want to update
+            stack_pointer_delta.  */
+         temp = expand_binop (Pmode,
+#ifdef STACK_GROWS_DOWNWARD
+                              sub_optab,
+#else
+                              add_optab,
+#endif
+                              stack_pointer_rtx,
+                              GEN_INT
+                                (PUSH_ROUNDING (GET_MODE_SIZE (GET_MODE (x)))),
+                              stack_pointer_rtx,
+                              0,
+                              OPTAB_LIB_WIDEN);
+         if (temp != stack_pointer_rtx)
+           emit_move_insn (stack_pointer_rtx, temp);
+#ifdef STACK_GROWS_DOWNWARD
+         offset1 = 0;
+         offset2 = GET_MODE_SIZE (submode);
+#else
+         offset1 = -PUSH_ROUNDING (GET_MODE_SIZE (GET_MODE (x)));
+         offset2 = (-PUSH_ROUNDING (GET_MODE_SIZE (GET_MODE (x)))
+                    + GET_MODE_SIZE (submode));
+#endif
+         emit_move_insn (change_address (x, submode,
+                                         gen_rtx_PLUS (Pmode,
+                                                       stack_pointer_rtx,
+                                                       GEN_INT (offset1))),
+                         gen_realpart (submode, y));
+         emit_move_insn (change_address (x, submode,
+                                         gen_rtx_PLUS (Pmode,
+                                                       stack_pointer_rtx,
+                                                       GEN_INT (offset2))),
+                         gen_imagpart (submode, y));
+       }
       /* If this is a stack, push the highpart first, so it
         will be in the argument order.
 
         In that case, change_address is used only to convert
         the mode, not to change the address.  */
-      if (stack)
+      else if (stack)
        {
          /* Note that the real part always precedes the imag part in memory
             regardless of machine's endianness.  */