]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
i386-protos.h (memory_address_length): Add new bool argument.
authorUros Bizjak <uros@gcc.gnu.org>
Sun, 21 Oct 2012 22:12:46 +0000 (00:12 +0200)
committerUros Bizjak <uros@gcc.gnu.org>
Sun, 21 Oct 2012 22:12:46 +0000 (00:12 +0200)
* config/i386/i386-protos.h (memory_address_length): Add new bool
argument.  Update all uses.
* config/i386/i386.c (memory_address_length): If not LEA insn, then
add length of addr32 prefix based on mode of base or index register.
(ix86_attr_length_address_default) <TYPE_LEA>: Do not handle SImode
addresses here.  Update call to memory_address_length.
(ix86_print_address_operand): Use SImode_address_operand predicate.
* config/i386/predicates.md (SImode_address_operand): New.
* config/i386/i386.md (lea<mode>): Use SImode_address_operand
to calculate "mode" attribute.  Use SImode_address_operand predicate
instead of open-coding accepted RTX codes.

From-SVN: r192660

gcc/ChangeLog
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c
gcc/config/i386/i386.md
gcc/config/i386/predicates.md

index a4c6e9e1400e9744642cc748121b3c90bb430c59..f7e2572ee1b39869c8431b6bffdfba9657938f54 100644 (file)
@@ -1,3 +1,17 @@
+2012-10-21  Uros Bizjak  <ubizjak@gmail.com>
+
+       * config/i386/i386-protos.h (memory_address_length): Add new bool
+       argument.  Update all uses.
+       * config/i386/i386.c (memory_address_length): If not LEA insn, then
+       add length of addr32 prefix based on mode of base or index register.
+       (ix86_attr_length_address_default) <TYPE_LEA>: Do not handle SImode
+       addresses here.  Update call to memory_address_length.
+       (ix86_print_address_operand): Use SImode_address_operand predicate.
+       * config/i386/predicates.md (SImode_address_operand): New.
+       * config/i386/i386.md (lea<mode>): Use SImode_address_operand
+       to calculate "mode" attribute.  Use SImode_address_operand predicate
+       instead of open-coding accepted RTX codes.
+
 2012-10-21  Joern Rennecke  <joern.rennecke@embecosm.com>
 
        * rtl.def (ADDR_DIFF_VEC): Fix comment typo.
        * calls.c (expand_call): Don't deal specifically with BLKmode values
        returned in naked registers.
        * expr.h (copy_blkmode_from_reg): Adjust prototype.
-       * expr.c (copy_blkmode_from_reg): Rename first parameter into TARGET and
-       make it required.  Assert that SRCREG hasn't BLKmode.  Add a couple of 
-       short-circuits for common cases and be prepared for sub-word registers.
+       * expr.c (copy_blkmode_from_reg): Rename first parameter into
+       TARGET and make it required.  Assert that SRCREG hasn't BLKmode.
+       Add a couple of short-circuits for common cases and be prepared
+       for sub-word registers.
        (expand_assignment): Call copy_blkmode_from_reg for BLKmode values
        returned in naked registers.
        (store_expr): Likewise.
@@ -61,7 +76,8 @@
 
 2012-10-19  Jan Hubicka  <jh@suse.cz>
 
-       * builtins.def (BUILT_IN_UNREACHABLE): Make ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST.
+       * builtins.def (BUILT_IN_UNREACHABLE): Make
+       ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST.
        * builtin-attrs.def (ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST): Define.
 
 2012-10-19  Michael Meissner  <meissner@linux.vnet.ibm.com>
index 2002bfcef5bc5b1f7def4e04a79b080fc88850a0..96971aeb628bb6f01ea56b5119fb55f5c7404ca5 100644 (file)
@@ -282,7 +282,7 @@ struct ix86_address
 };
 
 extern int ix86_decompose_address (rtx, struct ix86_address *);
-extern int memory_address_length (rtx addr);
+extern int memory_address_length (rtx, bool);
 extern void x86_output_aligned_bss (FILE *, tree, const char *,
                                    unsigned HOST_WIDE_INT, int);
 extern void x86_elf_aligned_common (FILE *, const char *,
index e095d987296628a0d1c3982a5667a9d3ef4fc262..742a34b3185f21c633b2eca643106bab0603f130 100644 (file)
@@ -14979,19 +14979,24 @@ ix86_print_operand_address (FILE *file, rtx addr)
   else
     {
       /* Print SImode register names to force addr32 prefix.  */
-      if (GET_CODE (addr) == SUBREG)
-       {
-         gcc_assert (TARGET_64BIT);
-         gcc_assert (GET_MODE (addr) == SImode);
-         gcc_assert (GET_MODE (SUBREG_REG (addr)) == DImode);
-         gcc_assert (!code);
-         code = 'l';
-       }
-      else if (GET_CODE (addr) == ZERO_EXTEND
-              || GET_CODE (addr) == AND)
+      if (SImode_address_operand (addr, VOIDmode))
        {
+#ifdef ENABLE_CHECKING
          gcc_assert (TARGET_64BIT);
-         gcc_assert (GET_MODE (addr) == DImode);
+         switch (GET_CODE (addr))
+           {
+           case SUBREG:
+             gcc_assert (GET_MODE (addr) == SImode);
+             gcc_assert (GET_MODE (SUBREG_REG (addr)) == DImode);
+             break;
+           case ZERO_EXTEND:
+           case AND:
+             gcc_assert (GET_MODE (addr) == DImode);
+             break;
+           default:
+             gcc_unreachable ();
+           }
+#endif
          gcc_assert (!code);
          code = 'l';
        }
@@ -23752,14 +23757,14 @@ assign_386_stack_local (enum machine_mode mode, enum ix86_stack_slot n)
 \f
 /* Calculate the length of the memory address in the instruction encoding.
    Includes addr32 prefix, does not include the one-byte modrm, opcode,
-   or other prefixes.  */
+   or other prefixes.  We never generate addr32 prefix for LEA insn.  */
 
 int
-memory_address_length (rtx addr)
+memory_address_length (rtx addr, bool lea)
 {
   struct ix86_address parts;
   rtx base, index, disp;
-  int len;
+  int len = 0;
   int ok;
 
   if (GET_CODE (addr) == PRE_DEC
@@ -23780,10 +23785,6 @@ memory_address_length (rtx addr)
   index = parts.index;
   disp = parts.disp;
 
-  /* Add length of addr32 prefix.  */
-  len = (GET_CODE (addr) == ZERO_EXTEND
-        || GET_CODE (addr) == AND);
-
   /* Rule of thumb:
        - esp as the base always wants an index,
        - ebp as the base always wants a displacement,
@@ -23796,13 +23797,13 @@ memory_address_length (rtx addr)
       /* esp (for its index) and ebp (for its displacement) need
         the two-byte modrm form.  Similarly for r12 and r13 in 64-bit
         code.  */
-      if (REG_P (addr)
-         && (addr == arg_pointer_rtx
-             || addr == frame_pointer_rtx
-             || REGNO (addr) == SP_REG
-             || REGNO (addr) == BP_REG
-             || REGNO (addr) == R12_REG
-             || REGNO (addr) == R13_REG))
+      if (REG_P (base)
+         && (base == arg_pointer_rtx
+             || base == frame_pointer_rtx
+             || REGNO (base) == SP_REG
+             || REGNO (base) == BP_REG
+             || REGNO (base) == R12_REG
+             || REGNO (base) == R13_REG))
        len = 1;
     }
 
@@ -23834,7 +23835,6 @@ memory_address_length (rtx addr)
            len += 1;
        }
     }
-
   else
     {
       /* Find the length of the displacement constant.  */
@@ -23870,6 +23870,12 @@ memory_address_length (rtx addr)
       break;
     }
 
+  /*  If this is not LEA instruction, add the length of addr32 prefix.  */
+  if (TARGET_64BIT && !lea
+      && ((base && GET_MODE (base) == SImode)
+         || (index && GET_MODE (index) == SImode)))
+    len += 1;
+
   return len;
 }
 
@@ -23921,7 +23927,8 @@ ix86_attr_length_immediate_default (rtx insn, bool shortform)
          case MODE_SI:
            len = 4;
            break;
-         /* Immediates for DImode instructions are encoded as 32bit sign extended values.  */
+         /* Immediates for DImode instructions are encoded
+            as 32bit sign extended values.  */
          case MODE_DI:
            len = 4;
            break;
@@ -23931,6 +23938,7 @@ ix86_attr_length_immediate_default (rtx insn, bool shortform)
       }
   return len;
 }
+
 /* Compute default value for "length_address" attribute.  */
 int
 ix86_attr_length_address_default (rtx insn)
@@ -23947,15 +23955,8 @@ ix86_attr_length_address_default (rtx insn)
       gcc_assert (GET_CODE (set) == SET);
 
       addr = SET_SRC (set);
-      if (TARGET_64BIT && get_attr_mode (insn) == MODE_SI)
-       {
-         if (GET_CODE (addr) == ZERO_EXTEND)
-           addr = XEXP (addr, 0);
-         if (GET_CODE (addr) == SUBREG)
-           addr = SUBREG_REG (addr);
-       }
 
-      return memory_address_length (addr);
+      return memory_address_length (addr, true);
     }
 
   extract_insn_cached (insn);
@@ -23977,7 +23978,7 @@ ix86_attr_length_address_default (rtx insn)
            if (*constraints == 'X')
              continue;
          }
-       return memory_address_length (XEXP (recog_data.operand[i], 0));
+       return memory_address_length (XEXP (recog_data.operand[i], 0), false);
       }
   return 0;
 }
index 299115d4ac469c214c9bf89186b8b4dcd6d0b6f2..049d53494f920e1dd5554b767ca5fd5af46817e4 100644 (file)
 {
   rtx addr = operands[1];
 
-  if (GET_CODE (addr) == SUBREG)
+  if (SImode_address_operand (addr, VOIDmode))
     {
       gcc_assert (TARGET_64BIT);
-      gcc_assert (<MODE>mode == SImode);
-      gcc_assert (GET_MODE (SUBREG_REG (addr)) == DImode);
-      return "lea{l}\t{%E1, %0|%0, %E1}";
-    }
-  else if (GET_CODE (addr) == ZERO_EXTEND
-          || GET_CODE (addr) == AND)
-    {
-      gcc_assert (TARGET_64BIT);
-      gcc_assert (<MODE>mode == DImode);
       return "lea{l}\t{%E1, %k0|%k0, %E1}";
     }
   else 
 
   /* Emit all operations in SImode for zero-extended addresses.  Recall
      that x86_64 inheretly zero-extends SImode operations to DImode.  */
-  if (GET_CODE (operands[1]) == ZERO_EXTEND
-      || GET_CODE (operands[1]) == AND)
+  if (SImode_address_operand (operands[1], VOIDmode))
     mode = SImode;
 
   ix86_split_lea_for_addr (curr_insn, operands, mode);
   DONE;
 }
   [(set_attr "type" "lea")
-   (set_attr "mode" "<MODE>")])
+   (set (attr "mode")
+     (if_then_else
+       (match_operand 1 "SImode_address_operand")
+       (const_string "SI")
+       (const_string "<MODE>")))])
 \f
 ;; Add instructions
 
   [(set_attr "type" "sse")
    (set_attr "atom_sse_attr" "prefetch")
    (set (attr "length_address")
-       (symbol_ref "memory_address_length (operands[0])"))
+       (symbol_ref "memory_address_length (operands[0], false)"))
    (set_attr "memory" "none")])
 
 (define_insn "*prefetch_3dnow"
 }
   [(set_attr "type" "mmx")
    (set (attr "length_address")
-       (symbol_ref "memory_address_length (operands[0])"))
+       (symbol_ref "memory_address_length (operands[0], false)"))
    (set_attr "memory" "none")])
 
 (define_expand "stack_protect_set"
index 6cf5651814a087e1bc609af4d96240839c17be98..4e5c17d8b37c4426c8411142c78c7ddd261d9699 100644 (file)
   return parts.seg == SEG_DEFAULT;
 })
 
+;; Return true for RTX codes that force SImode address.
+(define_predicate "SImode_address_operand"
+  (match_code "subreg,zero_extend,and"))
+
 ;; Return true if op if a valid base register, displacement or
 ;; sum of base register and displacement for VSIB addressing.
 (define_predicate "vsib_address_operand"
 ;; by the modRM array.
 (define_predicate "long_memory_operand"
   (and (match_operand 0 "memory_operand")
-       (match_test "memory_address_length (op)")))
+       (match_test "memory_address_length (op, false)")))
 
 ;; Return true if OP is a comparison operator that can be issued by fcmov.
 (define_predicate "fcmov_comparison_operator"