OSDN Git Service

* i386.md (ashlsi patterns): Call output_ashl instead of output_ashlsi3.
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 15 Apr 1999 01:28:04 +0000 (01:28 +0000)
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 15 Apr 1999 01:28:04 +0000 (01:28 +0000)
        (ashlqi): Use expander, separate LEA and SAL / ADD patterns; call
        output_ashl.
        (ashlhi): Likewise.
        * i386.h (output_ashl): Renamed from output_ashlsi3.
        * i386.c (output_ashl): Likewise; support HImode and QImode operands
        as well.

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

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

index 3739e5f..30d9a68 100644 (file)
@@ -1,6 +1,14 @@
 Thu Apr 15 01:03:21 1999  Jan Hubicka <hubicka@freesoft.cz>
                          Jeff Law <law@cygnus.com>
 
+       * i386.md (ashlsi patterns): Call output_ashl instead of output_ashlsi3.
+       (ashlqi): Use expander, separate LEA and SAL / ADD patterns; call
+       output_ashl.
+       (ashlhi): Likewise.
+       * i386.h (output_ashl): Renamed from output_ashlsi3.
+       * i386.c (output_ashl): Likewise; support HImode and QImode operands
+       as well.
+
        * i386.md (notsi, nothi, xorsi, xorhi, and xorqi patterns): Call
        memory_address_displacement_length instead of memory_address_length.
        * i386.c (memory_address_info): Renamed from memory_address_length.
index 5665800..50acbb1 100644 (file)
@@ -5497,7 +5497,7 @@ x86_adjust_cost (insn, link, dep_insn, cost)
 
       /* Stores stalls one cycle longer than other insns.  */
       if (is_fp_insn (insn) && cost && is_fp_store (dep_insn))
-        cost++;
+       cost++;
 
     case PROCESSOR_K6:
     default:
@@ -5543,34 +5543,50 @@ x86_adjust_cost (insn, link, dep_insn, cost)
      TARGET_DOUBLE_WITH_ADD.  */
 
 char *
-output_ashlsi3 (operands)
-     rtx *operands;
+output_ashl (insn, operands)
+     rtx insn, *operands;
 {
   /* Handle case where srcreg != dstreg.  */
   if (REG_P (operands[0]) && REGNO (operands[0]) != REGNO (operands[1]))
     {
       if (TARGET_DOUBLE_WITH_ADD && INTVAL (operands[2]) == 1)
-       {
-         output_asm_insn (AS2 (mov%L0,%1,%0), operands);
-         return AS2 (add%L0,%1,%0);
-       }
+       switch (GET_MODE (operands[0]))
+         {
+         case SImode:
+           output_asm_insn (AS2 (mov%L0,%1,%0), operands);
+           return AS2 (add%L0,%1,%0);
+         case HImode:
+           output_asm_insn (AS2 (mov%L0,%k1,%k0), operands);
+           if (i386_cc_probably_useless_p (insn))
+             {
+               CC_STATUS_INIT;
+               return AS2 (add%L0,%k1,%k0);
+             }
+           return AS2 (add%W0,%k1,%k0);
+         case QImode:
+           output_asm_insn (AS2 (mov%B0,%1,%0), operands);
+           return AS2 (add%B0,%1,%0);
+         default:
+           abort ();
+         }
       else
-        {
-          CC_STATUS_INIT;
+       {
+         CC_STATUS_INIT;
 
          /* This should be extremely rare (impossible?).  We can not encode a
             shift of the stack pointer using an lea instruction.  So copy the
             stack pointer into the destination register and use an lea.  */
          if (operands[1] == stack_pointer_rtx)
            {
-             output_asm_insn (AS2 (mov%L0,%1,%0), operands);
+             output_asm_insn (AS2 (mov%L0,%k1,%k0), operands);
              operands[1] = operands[0];
            }
 
          /* For shifts up to and including 3 bits, use lea.  */
-          operands[1] = gen_rtx_MULT (SImode, operands[1],
+         operands[1] = gen_rtx_MULT (SImode,
+                                     gen_rtx_REG (SImode, REGNO (operands[1])),
                                      GEN_INT (1 << INTVAL (operands[2])));
-         return AS2 (lea%L0,%a1,%0);
+         return AS2 (lea%L0,%a1,%k0);
        }
     }
 
@@ -5578,17 +5594,47 @@ output_ashlsi3 (operands)
 
   /* Handle variable shift.  */
   if (REG_P (operands[2]))
-    return AS2 (sal%L0,%b2,%0);
+    switch (GET_MODE (operands[0]))
+      {
+      case SImode:
+       return AS2 (sal%L0,%b2,%0);
+      case HImode:
+       if (REG_P (operands[0]) && i386_cc_probably_useless_p (insn))
+         {
+           CC_STATUS_INIT;
+           return AS2 (sal%L0,%b2,%k0);
+         }
+       else
+         return AS2 (sal%W0,%b2,%0);
+      case QImode:
+       return AS2 (sal%B0,%b2,%0);
+      default:
+       abort ();
+      }
 
   /* Always perform shift by 1 using an add instruction.  */
   if (REG_P (operands[0]) && operands[2] == const1_rtx)
-    return AS2 (add%L0,%0,%0);
+    switch (GET_MODE (operands[0]))
+      {
+      case SImode:
+       return AS2 (add%L0,%0,%0);
+      case HImode:
+       if (REG_P (operands[0]) && i386_cc_probably_useless_p (insn))
+         {
+           CC_STATUS_INIT;
+           return AS2 (add%L0,%k0,%k0);
+         }
+       else
+         return AS2 (add%W0,%0,%0);
+      case QImode:
+         return AS2 (add%B0,%0,%0);
+      default:
+         abort ();
+      }
 
 #if 0
-  /* ??? Currently disabled.  reg-stack currently stomps on the mode of
-     each insn.  Thus, we can not easily detect when we should use lea to
-     improve issue characteristics.  Until reg-stack is fixed, fall back to
-     sal instruction for Pentiums to avoid AGI stall.  */
+  /* ??? Currently disabled.  Because our model of Pentium is far from being
+     exact, this change will need some benchmarking.  */
   /* Shift reg by 2 or 3 use an lea instruction for Pentium if this is
      insn is expected to issue into the V pipe (the insn's mode will be
      TImode for a U pipe, and !TImode for a V pipe instruction).  */
@@ -5600,14 +5646,30 @@ output_ashlsi3 (operands)
       && GET_MODE (insn) != TImode)
     {
       CC_STATUS_INIT;
-      operands[1] = gen_rtx_MULT (SImode, operands[1],
+      operands[1] = gen_rtx_MULT (SImode, gen_rtx_REG (SImode, REGNO (operands[1])),
                                  GEN_INT (1 << INTVAL (operands[2])));
       return AS2 (lea%L0,%a1,%0);
     }
 #endif
 
   /* Otherwise use a shift instruction.  */
-  return AS2 (sal%L0,%2,%0);
+  switch (GET_MODE (operands[0]))
+    {
+    case SImode:
+      return AS2 (sal%L0,%2,%0);
+    case HImode:
+      if (REG_P (operands[0]) && i386_cc_probably_useless_p (insn))
+       {
+         CC_STATUS_INIT;
+         return AS2 (sal%L0,%2,%k0);
+       }
+      else
+       return AS2 (sal%W0,%2,%0);
+    case QImode:
+      return AS2 (sal%B0,%2,%0);
+    default:
+      abort ();
+    }
 }
 
 /* Given the memory address ADDR, calculate the length of the address or
index 1d752c7..a455d2d 100644 (file)
@@ -2765,7 +2765,7 @@ extern char *output_int_conditional_move ();
 extern char *output_fp_conditional_move ();
 extern int ix86_can_use_return_insn_p ();
 extern int small_shift_operand ();
-extern char *output_ashlsi3 ();
+extern char *output_ashl ();
 extern int memory_address_info ();
 
 #ifdef NOTYET
index da13109..39a06f2 100644 (file)
@@ -5079,18 +5079,33 @@ byte_xor_operation:
   ""
   "")
 
+(define_expand "ashlhi3"
+  [(set (match_operand:HI 0 "nonimmediate_operand" "")
+       (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "")
+                  (match_operand:HI 2 "nonmemory_operand" "")))]
+  ""
+  "")
+
+(define_expand "ashlqi3"
+  [(set (match_operand:QI 0 "nonimmediate_operand" "")
+       (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "")
+                  (match_operand:QI 2 "nonmemory_operand" "")))]
+  ""
+  "")
+
 ;; Pattern for shifts which can be encoded into an lea instruction.
 ;; This is kept as a separate pattern so that regmove can optimize cases
 ;; where we know the source and destination must match.
 ;;
 ;; Do not expose this pattern when optimizing for size since we never want
 ;; to use lea when optimizing for size since mov+sal is smaller than lea.
+
 (define_insn ""
   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
        (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,r")
                   (match_operand:SI 2 "small_shift_operand" "M,M")))]
   "! optimize_size"
-  "* return output_ashlsi3 (operands);")
+  "* return output_ashl (insn, operands);")
 
 ;; Generic left shift pattern to catch all cases not handled by the
 ;; shift pattern above.
@@ -5099,58 +5114,37 @@ byte_xor_operation:
        (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0")
                   (match_operand:SI 2 "nonmemory_operand" "cI")))]
   ""
-  "* return output_ashlsi3 (operands);")
+  "* return output_ashl (insn, operands);")
+
+(define_insn ""
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r")
+       (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0,r")
+                  (match_operand:HI 2 "small_shift_operand" "M,M")))]
+  "! optimize_size"
+  "* return output_ashl (insn, operands);")
 
-(define_insn "ashlhi3"
+(define_insn ""
   [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
        (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
                   (match_operand:HI 2 "nonmemory_operand" "cI")))]
   ""
-  "*
-{
-  if (REG_P (operands[2]))
-    {
-      if (REG_P (operands[0]) && i386_cc_probably_useless_p (insn))
-        {
-          CC_STATUS_INIT;
-          return AS2 (sal%L0,%b2,%k0);
-        }
-      return AS2 (sal%W0,%b2,%0);
-    }
+  "* return output_ashl (insn, operands);")
 
-  if (REG_P (operands[0]) && operands[2] == const1_rtx)
-    {
-      if (i386_cc_probably_useless_p (insn))
-        {
-          CC_STATUS_INIT;
-          return AS2 (add%L0,%k0,%k0);
-        }
-      return AS2 (add%W0,%0,%0);
-    }
-
-  if (REG_P (operands[0]) && i386_cc_probably_useless_p (insn))
-    {
-      CC_STATUS_INIT;
-      return AS2 (sal%L0,%2,%k0);
-    }
-  return AS2 (sal%W0,%2,%0);
-}")
+(define_insn ""
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=q,q")
+       (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,q")
+                  (match_operand:QI 2 "small_shift_operand" "M,M")))]
+  "! optimize_size"
+  "* return output_ashl (insn, operands);")
 
-(define_insn "ashlqi3"
+;; Generic left shift pattern to catch all cases not handled by the
+;; shift pattern above.
+(define_insn ""
   [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
        (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0")
                   (match_operand:QI 2 "nonmemory_operand" "cI")))]
   ""
-  "*
-{
-  if (REG_P (operands[2]))
-    return AS2 (sal%B0,%b2,%0);
-
-  if (REG_P (operands[0]) && operands[2] == const1_rtx)
-    return AS2 (add%B0,%0,%0);
-
-  return AS2 (sal%B0,%2,%0);
-}")
+  "* return output_ashl (insn, operands);")
 
 ;; See comment above `ashldi3' about how this works.