OSDN Git Service

* i386.md (*lea_general_[123]) New insns and splits.
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 30 Jul 2000 18:59:56 +0000 (18:59 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 30 Jul 2000 18:59:56 +0000 (18:59 +0000)
(addsi3 to lea splitter): Handle other modes too.
(shlsi3 to lea splitter): Likewise.
(addhi_1_lea, shlhi_1_lea): New patterns.
(addhi_1, shlhi_1): Conditionize by PARTIAL_REG_STALL.

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

gcc/ChangeLog
gcc/config/i386/i386.md

index 80482a3..bbbfc0a 100644 (file)
@@ -1,3 +1,11 @@
+Sun Jul 30 20:58:34 MET DST 2000  Jan Hubicka  <jh@suse.cz>
+
+       * i386.md (*lea_general_[123]) New insns and splits.
+       (addsi3 to lea splitter): Handle other modes too.
+       (shlsi3 to lea splitter): Likewise.
+       (addhi_1_lea, shlhi_1_lea): New patterns.
+       (addhi_1, shlhi_1): Conditionize by PARTIAL_REG_STALL.
+
 Sun Jul 30 20:51:25 MET DST 2000  Jan Hubicka  <jh@suse.cz>
 
        * recog.c (general_operand, nonimmediate_operand): Accept
index a47c6dc..eecb151 100644 (file)
   [(set_attr "type" "lea")
    (set_attr "mode" "SI")])
 
+;; The lea patterns for non-Pmodes needs to be matched by several
+;; insns converted to real lea by splitters.
+
+(define_insn_and_split "*lea_general_1"
+  [(set (match_operand 0 "register_operand" "=r")
+       (plus (plus (match_operand 1 "register_operand" "r")
+                   (match_operand 2 "register_operand" "r"))
+             (match_operand 3 "immediate_operand" "i")))]
+  "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode)
+   && (!TARGET_PARTIAL_REG_STALL || optimize_size)
+   && GET_MODE (operands[0]) == GET_MODE (operands[1])
+   && GET_MODE (operands[0]) == GET_MODE (operands[2])
+   && (GET_MODE (operands[0]) == GET_MODE (operands[3])
+       || GET_MODE (operands[3]) == VOIDmode)"
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+  "
+{
+  rtx pat;
+  operands[0] = gen_lowpart (SImode, operands[0]);
+  operands[1] = gen_lowpart (Pmode, operands[1]);
+  operands[2] = gen_lowpart (Pmode, operands[2]);
+  operands[3] = gen_lowpart (Pmode, operands[3]);
+  pat = gen_rtx_PLUS (Pmode, gen_rtx_PLUS (Pmode, operands[1], operands[2]),
+                     operands[3]);
+  if (Pmode != SImode)
+    pat = gen_rtx_SUBREG (SImode, pat, 0);
+  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
+  DONE;
+}"
+  [(set_attr "type" "lea")
+   (set_attr "mode" "SI")])
+
+(define_insn_and_split "*lea_general_2"
+  [(set (match_operand 0 "register_operand" "=r")
+       (plus (mult (match_operand 1 "register_operand" "r")
+                   (match_operand 2 "const248_operand" "i"))
+             (match_operand 3 "nonmemory_operand" "ri")))]
+  "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode)
+   && (!TARGET_PARTIAL_REG_STALL || optimize_size)
+   && GET_MODE (operands[0]) == GET_MODE (operands[1])
+   && (GET_MODE (operands[0]) == GET_MODE (operands[3])
+       || GET_MODE (operands[3]) == VOIDmode)"
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+  "
+{
+  rtx pat;
+  operands[0] = gen_lowpart (SImode, operands[0]);
+  operands[1] = gen_lowpart (Pmode, operands[1]);
+  operands[3] = gen_lowpart (Pmode, operands[3]);
+  pat = gen_rtx_PLUS (Pmode, gen_rtx_MULT (Pmode, operands[1], operands[2]),
+                     operands[3]);
+  if (Pmode != SImode)
+    pat = gen_rtx_SUBREG (SImode, pat, 0);
+  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
+  DONE;
+}"
+  [(set_attr "type" "lea")
+   (set_attr "mode" "SI")])
+
+(define_insn_and_split "*lea_general_3"
+  [(set (match_operand 0 "register_operand" "=r")
+       (plus (plus (mult (match_operand 1 "register_operand" "r")
+                         (match_operand 2 "const248_operand" "i"))
+                   (match_operand 3 "register_operand" "r"))
+             (match_operand 4 "immediate_operand" "i")))]
+  "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode)
+   && (!TARGET_PARTIAL_REG_STALL || optimize_size)
+   && GET_MODE (operands[0]) == GET_MODE (operands[1])
+   && GET_MODE (operands[0]) == GET_MODE (operands[3])"
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+  "
+{
+  rtx pat;
+  operands[0] = gen_lowpart (SImode, operands[0]);
+  operands[1] = gen_lowpart (Pmode, operands[1]);
+  operands[3] = gen_lowpart (Pmode, operands[3]);
+  operands[4] = gen_lowpart (Pmode, operands[4]);
+  pat = gen_rtx_PLUS (Pmode,
+                     gen_rtx_PLUS (Pmode, gen_rtx_MULT (Pmode, operands[1],
+                                                        operands[2]),
+                                   operands[3]),
+                     operands[4]);
+  if (Pmode != SImode)
+    pat = gen_rtx_SUBREG (SImode, pat, 0);
+  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
+  DONE;
+}"
+  [(set_attr "type" "lea")
+   (set_attr "mode" "SI")])
+
 (define_insn "*addsi_1"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r")
        (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r")
 
 ;; Convert lea to the lea pattern to avoid flags dependency.
 (define_split
-  [(set (match_operand:SI 0 "register_operand" "")
-       (plus:SI (match_operand:SI 1 "register_operand" "")
-                (match_operand:SI 2 "nonmemory_operand" "")))
+  [(set (match_operand 0 "register_operand" "")
+       (plus (match_operand 1 "register_operand" "")
+              (match_operand 2 "nonmemory_operand" "")))
    (clobber (reg:CC 17))]
-  "reload_completed
-   && true_regnum (operands[0]) != true_regnum (operands[1])"
-  [(set (match_dup 0)
-       (plus:SI (match_dup 1)
-                (match_dup 2)))]
-  "")
+  "reload_completed"
+  [(const_int 0)]
+  "
+{
+  rtx pat;
+  operands[0] = gen_lowpart (SImode, operands[0]);
+  /* In -fPIC mode the constructs like (const (unspec [symbol_ref]))
+     may confuse gen_lowpart.  */
+  if (GET_MODE (operands[0]) != Pmode)
+    {
+      operands[1] = gen_lowpart (Pmode, operands[1]);
+      operands[2] = gen_lowpart (Pmode, operands[2]);
+    }
+  pat = gen_rtx_PLUS (Pmode, operands[1], operands[2]);
+  if (Pmode != SImode)
+    pat = gen_rtx_SUBREG (SImode, pat, 0);
+  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
+  DONE;
+}")
 
 (define_insn "*addsi_2"
   [(set (reg 17)
 ;; type optimizations enabled by define-splits.  This is not important
 ;; for PII, and in fact harmful because of partial register stalls.
 
+(define_insn "*addhi_1_lea"
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,r")
+       (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,r")
+                (match_operand:HI 2 "general_operand" "ri,rm,rni")))
+   (clobber (reg:CC 17))]
+  "!TARGET_PARTIAL_REG_STALL
+   && ix86_binary_operator_ok (PLUS, HImode, operands)"
+  "*
+{
+  switch (get_attr_type (insn))
+    {
+    case TYPE_LEA:
+      return \"#\";
+    case TYPE_INCDEC:
+      if (operands[2] == const1_rtx)
+       return \"inc{w}\\t%0\";
+      else if (operands[2] == constm1_rtx
+              || (GET_CODE (operands[2]) == CONST_INT
+                  && INTVAL (operands[2]) == 65535))
+       return \"dec{w}\\t%0\";
+      abort();
+
+    default:
+      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
+        Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
+      if (GET_CODE (operands[2]) == CONST_INT
+          && (INTVAL (operands[2]) == 128
+             || (INTVAL (operands[2]) < 0
+                 && INTVAL (operands[2]) != -128)))
+       {
+         operands[2] = GEN_INT (-INTVAL (operands[2]));
+         return \"sub{w}\\t{%2, %0|%0, %2}\";
+       }
+      return \"add{w}\\t{%2, %0|%0, %2}\";
+    }
+}"
+  [(set (attr "type")
+     (if_then_else (eq_attr "alternative" "2")
+       (const_string "lea")
+       (if_then_else (match_operand:HI 2 "incdec_operand" "")
+          (const_string "incdec")
+          (const_string "alu"))))
+   (set_attr "mode" "HI,HI,SI")])
+
 (define_insn "*addhi_1"
   [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
        (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
                 (match_operand:HI 2 "general_operand" "ri,rm")))
    (clobber (reg:CC 17))]
-  "ix86_binary_operator_ok (PLUS, HImode, operands)"
+  "TARGET_PARTIAL_REG_STALL
+   && ix86_binary_operator_ok (PLUS, HImode, operands)"
   "*
 {
   switch (get_attr_type (insn))
   "ix86_expand_binary_operator (PLUS, QImode, operands); DONE;")
 
 ;; %%% Potential partial reg stall on alternative 2.  What to do?
+(define_insn "*addqi_1_lea"
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r,r")
+       (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0,r")
+                (match_operand:QI 2 "general_operand" "qn,qmn,rn,rn")))
+   (clobber (reg:CC 17))]
+  "!TARGET_PARTIAL_REG_STALL
+   && ix86_binary_operator_ok (PLUS, QImode, operands)"
+  "*
+{
+  int widen = (which_alternative == 2);
+  switch (get_attr_type (insn))
+    {
+    case TYPE_LEA:
+      return \"#\";
+    case TYPE_INCDEC:
+      if (operands[2] == const1_rtx)
+       return widen ? \"inc{l}\\t%k0\" : \"inc{b}\\t%0\";
+      else if (operands[2] == constm1_rtx
+              || (GET_CODE (operands[2]) == CONST_INT
+                  && INTVAL (operands[2]) == 255))
+       return widen ? \"dec{l}\\t%k0\" : \"dec{b}\\t%0\";
+      abort();
+
+    default:
+      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
+        Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
+      if (GET_CODE (operands[2]) == CONST_INT
+          && (INTVAL (operands[2]) == 128
+             || (INTVAL (operands[2]) < 0
+                 && INTVAL (operands[2]) != -128)))
+       {
+         operands[2] = GEN_INT (-INTVAL (operands[2]));
+         if (widen)
+           return \"sub{l}\\t{%2, %k0|%k0, %2}\";
+         else
+           return \"sub{b}\\t{%2, %0|%0, %2}\";
+       }
+      if (widen)
+        return \"add{l}\\t{%k2, %k0|%k0, %k2}\";
+      else
+        return \"add{b}\\t{%2, %0|%0, %2}\";
+    }
+}"
+  [(set (attr "type")
+     (if_then_else (eq_attr "alternative" "3")
+       (const_string "lea")
+       (if_then_else (match_operand:HI 2 "incdec_operand" "")
+          (const_string "incdec")
+          (const_string "alu"))))
+   (set_attr "mode" "HI,HI,SI,SI")])
+
 (define_insn "*addqi_1"
   [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r")
        (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
                 (match_operand:QI 2 "general_operand" "qn,qmn,rn")))
    (clobber (reg:CC 17))]
-  "ix86_binary_operator_ok (PLUS, QImode, operands)"
+  "TARGET_PARTIAL_REG_STALL
+   && ix86_binary_operator_ok (PLUS, QImode, operands)"
   "*
 {
   int widen = (which_alternative == 2);
 
 ;; Convert lea to the lea pattern to avoid flags dependency.
 (define_split
-  [(set (match_operand:SI 0 "register_operand" "")
-       (ashift:SI (match_operand:SI 1 "register_operand" "")
-                  (match_operand:QI 2 "immediate_operand" "")))
+  [(set (match_operand 0 "register_operand" "")
+       (ashift (match_operand 1 "register_operand" "")
+                (match_operand:QI 2 "const_int_operand" "")))
    (clobber (reg:CC 17))]
-  "reload_completed
-   && true_regnum (operands[0]) != true_regnum (operands[1])"
-  [(set (match_dup 0)
-       (mult:SI (match_dup 1)
-                (match_dup 2)))]
-  "operands[2] = GEN_INT (1 << INTVAL (operands[2]));")
+  "reload_completed"
+  [(const_int 0)]
+  "
+{
+  rtx pat;
+  operands[0] = gen_lowpart (SImode, operands[0]);
+  operands[1] = gen_lowpart (Pmode, operands[1]);
+  operands[2] = GEN_INT (1 << INTVAL (operands[2]));
+  pat = gen_rtx_MULT (Pmode, operands[1], operands[2]);
+  if (Pmode != SImode)
+    pat = gen_rtx_SUBREG (SImode, pat, 0);
+  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
+  DONE;
+}")
 
 ;; This pattern can't accept a variable shift count, since shifts by
 ;; zero don't affect the flags.  We assume that shifts by constant
   "TARGET_HIMODE_MATH"
   "ix86_expand_binary_operator (ASHIFT, HImode, operands); DONE;")
 
+(define_insn "*ashlhi3_1_lea"
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
+       (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0,r")
+                  (match_operand:QI 2 "nonmemory_operand" "cI,M")))
+   (clobber (reg:CC 17))]
+  "!TARGET_PARTIAL_REG_STALL
+   && ix86_binary_operator_ok (ASHIFT, HImode, operands)"
+  "*
+{
+  switch (get_attr_type (insn))
+    {
+    case TYPE_LEA:
+      return \"#\";
+    case TYPE_ALU:
+      if (operands[2] != const1_rtx)
+       abort ();
+      return \"add{w}\\t{%0, %0|%0, %0}\";
+
+    default:
+      if (REG_P (operands[2]))
+       return \"sal{w}\\t{%b2, %0|%0, %b2}\";
+      else if (GET_CODE (operands[2]) == CONST_INT
+              && INTVAL (operands[2]) == 1
+              && (TARGET_PENTIUM || TARGET_PENTIUMPRO))
+       return \"sal{w}\\t%0\";
+      else
+       return \"sal{w}\\t{%2, %0|%0, %2}\";
+    }
+}"
+  [(set (attr "type")
+     (cond [(eq_attr "alternative" "1")
+             (const_string "lea")
+            (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
+                         (const_int 0))
+                     (match_operand 0 "register_operand" ""))
+                (match_operand 2 "const1_operand" ""))
+             (const_string "alu")
+          ]
+          (const_string "ishift")))
+   (set_attr "mode" "HI,SI")])
+
 (define_insn "*ashlhi3_1"
   [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
        (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
                   (match_operand:QI 2 "nonmemory_operand" "cI")))
    (clobber (reg:CC 17))]
-  "ix86_binary_operator_ok (ASHIFT, HImode, operands)"
+  "TARGET_PARTIAL_REG_STALL
+   && ix86_binary_operator_ok (ASHIFT, HImode, operands)"
   "*
 {
   switch (get_attr_type (insn))
   "ix86_expand_binary_operator (ASHIFT, QImode, operands); DONE;")
 
 ;; %%% Potential partial reg stall on alternative 2.  What to do?
+
+(define_insn "*ashlqi3_1_lea"
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r,r")
+       (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,r")
+                  (match_operand:QI 2 "nonmemory_operand" "cI,cI,r")))
+   (clobber (reg:CC 17))]
+  "!TARGET_PARTIAL_REG_STALL
+   && ix86_binary_operator_ok (ASHIFT, QImode, operands)"
+  "*
+{
+  switch (get_attr_type (insn))
+    {
+    case TYPE_LEA:
+      return \"#\";
+    case TYPE_ALU:
+      if (operands[2] != const1_rtx)
+       abort ();
+      if (NON_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 (get_attr_mode (insn) == MODE_SI)
+           return \"sal{l}\\t{%b2, %k0|%k0, %b2}\";
+         else
+           return \"sal{b}\\t{%b2, %0|%0, %b2}\";
+       }
+      else if (GET_CODE (operands[2]) == CONST_INT
+              && INTVAL (operands[2]) == 1
+              && (TARGET_PENTIUM || TARGET_PENTIUMPRO))
+       {
+         if (get_attr_mode (insn) == MODE_SI)
+           return \"sal{l}\\t%0\";
+         else
+           return \"sal{b}\\t%0\";
+       }
+      else
+       {
+         if (get_attr_mode (insn) == MODE_SI)
+           return \"sal{l}\\t{%2, %k0|%k0, %2}\";
+         else
+           return \"sal{b}\\t{%2, %0|%0, %2}\";
+       }
+    }
+}"
+  [(set (attr "type")
+     (cond [(eq_attr "alternative" "2")
+             (const_string "lea")
+            (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
+                         (const_int 0))
+                     (match_operand 0 "register_operand" ""))
+                (match_operand 2 "const1_operand" ""))
+             (const_string "alu")
+          ]
+          (const_string "ishift")))
+   (set_attr "mode" "QI,SI,SI")])
+
 (define_insn "*ashlqi3_1"
   [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r")
        (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
                   (match_operand:QI 2 "nonmemory_operand" "cI,cI")))
    (clobber (reg:CC 17))]
-  "ix86_binary_operator_ok (ASHIFT, QImode, operands)"
+  "TARGET_PARTIAL_REG_STALL
+   && ix86_binary_operator_ok (ASHIFT, QImode, operands)"
   "*
 {
   switch (get_attr_type (insn))