OSDN Git Service

* config/i386/constraints.md (Ym): New constraint.
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 9 Feb 2007 18:17:09 +0000 (18:17 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 9 Feb 2007 18:17:09 +0000 (18:17 +0000)
        * config/i386/i386.md (movsi_1): Change Y2 to Yi constraints.
        (movdi_1_rex64): Split sse and xmm general register moves from
        memory move alternatives.  Use conditional register constraints.
        (movsf_1, movdf_integer): Likewise.
        (zero_extendsidi2_32, zero_extendsidi2_rex64): Likewise.
        (movdf_integer_rex64): New.
        (pushsf_rex64): Fix output constraints.
        * config/i386/sse.md (sse2_loadld): Split rm alternative, use Yi.
        (sse2_stored): Likewise.
        (sse2_storeq_rex64): New.
        * config/i386/i386.c (x86_inter_unit_moves): Enable for not
        amd and not generic.
        (ix86_secondary_memory_needed): Don't bypass TARGET_INTER_UNIT_MOVES
        for optimize_size.  Remove SF/DFmode hack.

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

gcc/ChangeLog
gcc/config/i386/constraints.md
gcc/config/i386/i386.c
gcc/config/i386/i386.md
gcc/config/i386/sse.md

index de6a753..52ed599 100644 (file)
@@ -1,3 +1,21 @@
+2007-02-09  Richard Henderson  <rth@redhat.com>
+
+       * config/i386/constraints.md (Ym): New constraint.
+       * config/i386/i386.md (movsi_1): Change Y2 to Yi constraints.
+       (movdi_1_rex64): Split sse and xmm general register moves from
+       memory move alternatives.  Use conditional register constraints.
+       (movsf_1, movdf_integer): Likewise.
+       (zero_extendsidi2_32, zero_extendsidi2_rex64): Likewise.
+       (movdf_integer_rex64): New.
+       (pushsf_rex64): Fix output constraints.
+       * config/i386/sse.md (sse2_loadld): Split rm alternative, use Yi.
+       (sse2_stored): Likewise.
+       (sse2_storeq_rex64): New.
+       * config/i386/i386.c (x86_inter_unit_moves): Enable for not
+       amd and not generic.
+       (ix86_secondary_memory_needed): Don't bypass TARGET_INTER_UNIT_MOVES
+       for optimize_size.  Remove SF/DFmode hack.
+
 2007-02-09  Dwarakanath Rajagopal <dwarak.rajagopal@amd.com>
 
         * config/i386/driver-i386.c: Turn on -mtune=native for AMDFAM10.
index f5b7c51..8f3e3ce 100644 (file)
@@ -86,6 +86,7 @@
 ;; We use the Y prefix to denote any number of conditional register sets:
 ;;  2  SSE2 enabled
 ;;  i  SSE2 inter-unit moves enabled
+;;  m  MMX inter-unit moves enabled
 
 (define_register_constraint "Y2" "TARGET_SSE2 ? SSE_REGS : NO_REGS"
  "@internal Any SSE register, when SSE2 is enabled.")
  "TARGET_SSE2 && TARGET_INTER_UNIT_MOVES ? SSE_REGS : NO_REGS"
  "@internal Any SSE register, when SSE2 and inter-unit moves are enabled.")
 
+(define_register_constraint "Ym"
+ "TARGET_MMX && TARGET_INTER_UNIT_MOVES ? MMX_REGS : NO_REGS"
+ "@internal Any MMX register, when inter-unit moves are enabled.")
+
 ;; Integer constant constraints.
 (define_constraint "I"
   "Integer constant in the range 0 @dots{} 31, for 32-bit shifts."
index 2dddd69..e5ff76e 100644 (file)
@@ -1161,9 +1161,7 @@ const int x86_sse_load0_by_pxor = m_PPRO | m_PENT4 | m_NOCONA;
 const int x86_use_ffreep = m_ATHLON_K8_AMDFAM10;
 const int x86_use_incdec = ~(m_PENT4 | m_NOCONA | m_CORE2 | m_GENERIC);
 
-/* ??? Allowing interunit moves makes it all too easy for the compiler to put
-   integer data in xmm registers.  Which results in pretty abysmal code.  */
-const int x86_inter_unit_moves = 0 /* ~(m_ATHLON_K8) */;
+const int x86_inter_unit_moves = ~(m_ATHLON_K8_AMDFAM10 | m_GENERIC);
 
 const int x86_ext_80387_constants = m_K6_GEODE | m_ATHLON_K8 | m_PENT4
                                     | m_NOCONA | m_PPRO | m_CORE2 | m_GENERIC;
@@ -18301,18 +18299,12 @@ ix86_secondary_memory_needed (enum reg_class class1, enum reg_class class2,
 
       /* If the target says that inter-unit moves are more expensive
         than moving through memory, then don't generate them.  */
-      if (!TARGET_INTER_UNIT_MOVES && !optimize_size)
+      if (!TARGET_INTER_UNIT_MOVES)
        return true;
 
       /* Between SSE and general, we have moves no larger than word size.  */
       if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
        return true;
-
-      /* ??? For the cost of one register reformat penalty, we could use
-        the same instructions to move SFmode and DFmode data, but the
-        relevant move patterns don't support those alternatives.  */
-      if (mode == SFmode || mode == DFmode)
-       return true;
     }
 
   return false;
index ffb575a..4f194d4 100644 (file)
 
 (define_insn "*movsi_1"
   [(set (match_operand:SI 0 "nonimmediate_operand"
-                       "=r  ,m  ,*y,*y,?rm,?*y,*x,*x,?r ,m ,?*Y2,*x")
+                       "=r  ,m  ,*y,*y,?rm,?*y,*x,*x,?r ,m ,?*Yi,*x")
        (match_operand:SI 1 "general_operand"
-                       "rinm,rin,C ,*y,*y ,rm ,C ,*x,*Y2,*x,r   ,m "))]
+                       "rinm,rin,C ,*y,*y ,rm ,C ,*x,*Yi,*x,r   ,m "))]
   "!(MEM_P (operands[0]) && MEM_P (operands[1]))"
 {
   switch (get_attr_type (insn))
 
 (define_insn "*movdi_1_rex64"
   [(set (match_operand:DI 0 "nonimmediate_operand"
-               "=r,r  ,r,m ,!m,*y,*y,?rm,?*y,*x,*x,?rm,?*x,?*x,?*y")
+         "=r,r  ,r,m ,!m,*y,*y,?r ,m ,?*Ym,*y,*x,*x,?r ,m,?*Yi,*x,?*x,?*Ym")
        (match_operand:DI 1 "general_operand"
-               "Z ,rem,i,re,n ,C ,*y,*y ,rm ,C ,*x,*x ,rm ,*y ,*x"))]
+         "Z ,rem,i,re,n ,C ,*y,*Ym,*y,r   ,m ,C ,*x,*Yi,*x,r  ,m ,*Ym,*x"))]
   "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
 {
   switch (get_attr_type (insn))
     {
     case TYPE_SSECVT:
-      if (which_alternative == 13)
+      if (SSE_REG_P (operands[0]))
        return "movq2dq\t{%1, %0|%0, %1}";
       else
        return "movdq2q\t{%1, %0|%0, %1}";
+
     case TYPE_SSEMOV:
       if (get_attr_mode (insn) == MODE_TI)
-         return "movdqa\t{%1, %0|%0, %1}";
+       return "movdqa\t{%1, %0|%0, %1}";
       /* FALLTHRU */
+
     case TYPE_MMXMOV:
-      /* Moves from and into integer register is done using movd opcode with
-        REX prefix.  */
+      /* Moves from and into integer register is done using movd
+        opcode with REX prefix.  */
       if (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1]))
-         return "movd\t{%1, %0|%0, %1}";
+       return "movd\t{%1, %0|%0, %1}";
       return "movq\t{%1, %0|%0, %1}";
+
     case TYPE_SSELOG1:
     case TYPE_MMXADD:
       return "pxor\t%0, %0";
+
     case TYPE_MULTI:
       return "#";
+
     case TYPE_LEA:
       return "lea{q}\t{%a1, %0|%0, %a1}";
+
     default:
       gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1]));
       if (get_attr_mode (insn) == MODE_SI)
   [(set (attr "type")
      (cond [(eq_attr "alternative" "5")
              (const_string "mmxadd")
-           (eq_attr "alternative" "6,7,8")
+           (eq_attr "alternative" "6,7,8,9,10")
              (const_string "mmxmov")
-           (eq_attr "alternative" "9")
+           (eq_attr "alternative" "11")
              (const_string "sselog1")
-           (eq_attr "alternative" "10,11,12")
+           (eq_attr "alternative" "12,13,14,15,16")
              (const_string "ssemov")
-           (eq_attr "alternative" "13,14")
+           (eq_attr "alternative" "17,18")
              (const_string "ssecvt")
            (eq_attr "alternative" "4")
              (const_string "multi")
              (const_string "lea")
           ]
           (const_string "imov")))
-   (set_attr "modrm" "*,0,0,*,*,*,*,*,*,*,*,*,*,*,*")
-   (set_attr "length_immediate" "*,4,8,*,*,*,*,*,*,*,*,*,*,*,*")
-   (set_attr "mode" "SI,DI,DI,DI,SI,DI,DI,DI,DI,TI,TI,DI,DI,DI,DI")])
+   (set_attr "modrm" "*,0,0,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")
+   (set_attr "length_immediate" "*,4,8,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")
+   (set_attr "mode" "SI,DI,DI,DI,SI,DI,DI,DI,DI,DI,DI,TI,TI,DI,DI,DI,DI,DI,DI")])
 
 ;; Stores and loads of ax to arbitrary constant address.
 ;; We fake an second form of instruction to force reload to load address
    (set_attr "mode" "SF,SI,SF")])
 
 (define_insn "*pushsf_rex64"
-  [(set (match_operand:SF 0 "push_operand" "=X,X,X")
+  [(set (match_operand:SF 0 "push_operand" "=<,<,<")
        (match_operand:SF 1 "nonmemory_no_elim_operand" "f,rF,x"))]
   "TARGET_64BIT"
 {
 
 (define_insn "*movsf_1"
   [(set (match_operand:SF 0 "nonimmediate_operand"
-         "=f,m   ,f,r  ,m    ,x,x,x ,m   ,!*y,!rm,!*y")
+         "=f,m,f,r  ,m ,x,x,x ,m,*y,m ,*y,Yi,r ,*Ym,r  ")
        (match_operand:SF 1 "general_operand"
-         "fm,f,G   ,rmF,Fr,C   ,x   ,xm,x,rm ,*y ,*y"))]
+         "fm,f,G,rmF,Fr,C,x,xm,x,m ,*y,*y,r ,Yi,r  ,*Ym"))]
   "!(MEM_P (operands[0]) && MEM_P (operands[1]))
    && (reload_in_progress || reload_completed
        || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
        return "movaps\t{%1, %0|%0, %1}";
       else
        return "movss\t{%1, %0|%0, %1}";
-    case 7:
-    case 8:
+    case 7: case 8:
       return "movss\t{%1, %0|%0, %1}";
 
-    case 9:
-    case 10:
+    case 9: case 10:
+    case 12: case 13: case 14: case 15:
       return "movd\t{%1, %0|%0, %1}";
 
     case 11:
       gcc_unreachable ();
     }
 }
-  [(set_attr "type" "fmov,fmov,fmov,imov,imov,sselog1,ssemov,ssemov,ssemov,mmxmov,mmxmov,mmxmov")
+  [(set_attr "type" "fmov,fmov,fmov,imov,imov,sselog1,ssemov,ssemov,ssemov,mmxmov,mmxmov,mmxmov,ssemov,ssemov,mmxmov,mmxmov")
    (set (attr "mode")
         (cond [(eq_attr "alternative" "3,4,9,10")
                 (const_string "SI")
              ]
              (const_string "DF")))])
 
+(define_insn "*movdf_integer_rex64"
+  [(set (match_operand:DF 0 "nonimmediate_operand"
+               "=f,m,f,r  ,m ,Y2*x,Y2*x,Y2*x,m   ,Yi,r ")
+       (match_operand:DF 1 "general_operand"
+               "fm,f,G,rmF,Fr,C   ,Y2*x,m   ,Y2*x,r ,Yi"))]
+  "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))
+   && (reload_in_progress || reload_completed
+       || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
+       || (!(TARGET_SSE2 && TARGET_SSE_MATH) && optimize_size
+          && standard_80387_constant_p (operands[1]))
+       || GET_CODE (operands[1]) != CONST_DOUBLE
+       || memory_operand (operands[0], DFmode))"
+{
+  switch (which_alternative)
+    {
+    case 0:
+      return output_387_reg_move (insn, operands);
+
+    case 1:
+      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+        return "fstp%z0\t%y0";
+      else
+        return "fst%z0\t%y0";
+
+    case 2:
+      return standard_80387_constant_opcode (operands[1]);
+
+    case 3:
+    case 4:
+      return "#";
+
+    case 5:
+      switch (get_attr_mode (insn))
+       {
+       case MODE_V4SF:
+         return "xorps\t%0, %0";
+       case MODE_V2DF:
+         return "xorpd\t%0, %0";
+       case MODE_TI:
+         return "pxor\t%0, %0";
+       default:
+         gcc_unreachable ();
+       }
+    case 6:
+    case 7:
+    case 8:
+      switch (get_attr_mode (insn))
+       {
+       case MODE_V4SF:
+         return "movaps\t{%1, %0|%0, %1}";
+       case MODE_V2DF:
+         return "movapd\t{%1, %0|%0, %1}";
+       case MODE_TI:
+         return "movdqa\t{%1, %0|%0, %1}";
+       case MODE_DI:
+         return "movq\t{%1, %0|%0, %1}";
+       case MODE_DF:
+         return "movsd\t{%1, %0|%0, %1}";
+       case MODE_V1DF:
+         return "movlpd\t{%1, %0|%0, %1}";
+       case MODE_V2SF:
+         return "movlps\t{%1, %0|%0, %1}";
+       default:
+         gcc_unreachable ();
+       }
+
+    case 9:
+    case 10:
+      return "movd\t{%1, %0|%0, %1}";
+
+    default:
+      gcc_unreachable();
+    }
+}
+  [(set_attr "type" "fmov,fmov,fmov,multi,multi,sselog1,ssemov,ssemov,ssemov,ssemov,ssemov")
+   (set (attr "mode")
+        (cond [(eq_attr "alternative" "0,1,2")
+                (const_string "DF")
+              (eq_attr "alternative" "3,4,9,10")
+                (const_string "DI")
+
+              /* For SSE1, we have many fewer alternatives.  */
+              (eq (symbol_ref "TARGET_SSE2") (const_int 0))
+                (cond [(eq_attr "alternative" "5,6")
+                         (const_string "V4SF")
+                      ]
+                  (const_string "V2SF"))
+
+              /* xorps is one byte shorter.  */
+              (eq_attr "alternative" "5")
+                (cond [(ne (symbol_ref "optimize_size")
+                           (const_int 0))
+                         (const_string "V4SF")
+                       (ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR")
+                           (const_int 0))
+                         (const_string "TI")
+                      ]
+                      (const_string "V2DF"))
+
+              /* For architectures resolving dependencies on
+                 whole SSE registers use APD move to break dependency
+                 chains, otherwise use short move to avoid extra work.
+
+                 movaps encodes one byte shorter.  */
+              (eq_attr "alternative" "6")
+                (cond
+                  [(ne (symbol_ref "optimize_size")
+                       (const_int 0))
+                     (const_string "V4SF")
+                   (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY")
+                       (const_int 0))
+                     (const_string "V2DF")
+                  ]
+                  (const_string "DF"))
+              /* For architectures resolving dependencies on register
+                 parts we may avoid extra work to zero out upper part
+                 of register.  */
+              (eq_attr "alternative" "7")
+                (if_then_else
+                  (ne (symbol_ref "TARGET_SSE_SPLIT_REGS")
+                      (const_int 0))
+                  (const_string "V1DF")
+                  (const_string "DF"))
+             ]
+             (const_string "DF")))])
+
 (define_insn "*movdf_integer"
   [(set (match_operand:DF 0 "nonimmediate_operand"
                "=f,m,f,r  ,o ,Y2*x,Y2*x,Y2*x,m   ")
        (match_operand:DF 1 "general_operand"
                "fm,f,G,roF,Fr,C   ,Y2*x,m   ,Y2*x"))]
   "!(MEM_P (operands[0]) && MEM_P (operands[1]))
-   && ((!optimize_size && TARGET_INTEGER_DFMODE_MOVES) || TARGET_64BIT)
+   && !optimize_size && TARGET_INTEGER_DFMODE_MOVES
    && (reload_in_progress || reload_completed
        || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
        || (!(TARGET_SSE2 && TARGET_SSE_MATH) && optimize_size
   [(set (match_operand:DI 0 "register_operand" "=r")
      (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm")))]
   ""
-  "if (!TARGET_64BIT)
-     {
-       emit_insn (gen_zero_extendsidi2_32 (operands[0], operands[1]));
-       DONE;
-     }
-  ")
+{
+  if (!TARGET_64BIT)
+    {
+      emit_insn (gen_zero_extendsidi2_32 (operands[0], operands[1]));
+      DONE;
+    }
+})
 
 (define_insn "zero_extendsidi2_32"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?*o,?*y,?*Y2")
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?o,?*Ym,*y,?*Yi,*Y2")
        (zero_extend:DI
-        (match_operand:SI 1 "nonimmediate_operand" "0,rm,r,rm,rm")))
+        (match_operand:SI 1 "nonimmediate_operand" "0,rm,r ,r   ,m ,r   ,m")))
    (clobber (reg:CC FLAGS_REG))]
   "!TARGET_64BIT"
   "@
    #
    #
    movd\t{%1, %0|%0, %1}
+   movd\t{%1, %0|%0, %1}
+   movd\t{%1, %0|%0, %1}
    movd\t{%1, %0|%0, %1}"
-  [(set_attr "mode" "SI,SI,SI,DI,TI")
-   (set_attr "type" "multi,multi,multi,mmxmov,ssemov")])
+  [(set_attr "mode" "SI,SI,SI,DI,DI,TI,TI")
+   (set_attr "type" "multi,multi,multi,mmxmov,mmxmov,ssemov,ssemov")])
 
 (define_insn "zero_extendsidi2_rex64"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o,?*y,?*Y2")
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o,?*Ym,*y,?*Yi,*Y2")
      (zero_extend:DI
-       (match_operand:SI 1 "nonimmediate_operand" "rm,0,rm,rm")))]
+       (match_operand:SI 1 "nonimmediate_operand"  "rm,0,r   ,m ,r   ,m")))]
   "TARGET_64BIT"
   "@
    mov\t{%k1, %k0|%k0, %k1}
    #
    movd\t{%1, %0|%0, %1}
+   movd\t{%1, %0|%0, %1}
+   movd\t{%1, %0|%0, %1}
    movd\t{%1, %0|%0, %1}"
-  [(set_attr "type" "imovx,imov,mmxmov,ssemov")
-   (set_attr "mode" "SI,DI,SI,SI")])
+  [(set_attr "type" "imovx,imov,mmxmov,mmxmov,ssemov,ssemov")
+   (set_attr "mode" "SI,DI,DI,DI,TI,TI")])
 
 (define_split
   [(set (match_operand:DI 0 "memory_operand" "")
index 50abb8a..ed1de19 100644 (file)
   "operands[2] = CONST0_RTX (V4SImode);")
 
 (define_insn "sse2_loadld"
-  [(set (match_operand:V4SI 0 "register_operand"       "=Y2,x,x")
+  [(set (match_operand:V4SI 0 "register_operand"       "=Y2,Yi,x,x")
        (vec_merge:V4SI
          (vec_duplicate:V4SI
-           (match_operand:SI 2 "nonimmediate_operand" "mr ,m,x"))
-         (match_operand:V4SI 1 "reg_or_0_operand"     " C ,C,0")
+           (match_operand:SI 2 "nonimmediate_operand" "m  ,r ,m,x"))
+         (match_operand:V4SI 1 "reg_or_0_operand"     "C  ,C ,C,0")
          (const_int 1)))]
   "TARGET_SSE"
   "@
    movd\t{%2, %0|%0, %2}
+   movd\t{%2, %0|%0, %2}
    movss\t{%2, %0|%0, %2}
    movss\t{%2, %0|%0, %2}"
   [(set_attr "type" "ssemov")
-   (set_attr "mode" "TI,V4SF,SF")])
+   (set_attr "mode" "TI,TI,V4SF,SF")])
 
-;; ??? The hardware supports more, but TARGET_INTER_UNIT_MOVES must
-;; be taken into account, and movdi isn't fully populated even without.
 (define_insn_and_split "sse2_stored"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=mx")
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=mx,r")
        (vec_select:SI
-         (match_operand:V4SI 1 "register_operand" "x")
+         (match_operand:V4SI 1 "register_operand" "x,Yi")
          (parallel [(const_int 0)])))]
   "TARGET_SSE"
   "#"
   "TARGET_SSE"
   "")
 
-;; ??? The hardware supports more, but TARGET_INTER_UNIT_MOVES must
-;; be taken into account, and movdi isn't fully populated even without.
+(define_insn "*sse2_storeq_rex64"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=mx,r")
+       (vec_select:DI
+         (match_operand:V2DI 1 "register_operand" "x,Yi")
+         (parallel [(const_int 0)])))]
+  "TARGET_64BIT && TARGET_SSE"
+  "#")
+
 (define_insn "*sse2_storeq"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=mx")
        (vec_select:DI