aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorUros Bizjak <uros@gcc.gnu.org>2012-10-22 00:12:46 +0200
committerUros Bizjak <uros@gcc.gnu.org>2012-10-22 00:12:46 +0200
commitcab54dfa3ad330dd2ccb876e85112cc4363786d5 (patch)
treeb7154eb94cb5fcc8262e1ed94e79ec04396f1824 /gcc
parent84cac7eff72290d1b2a57c75df602a02ffd2f56e (diff)
downloadgcc-cab54dfa3ad330dd2ccb876e85112cc4363786d5.zip
gcc-cab54dfa3ad330dd2ccb876e85112cc4363786d5.tar.gz
gcc-cab54dfa3ad330dd2ccb876e85112cc4363786d5.tar.bz2
i386-protos.h (memory_address_length): Add new bool argument.
* 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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog24
-rw-r--r--gcc/config/i386/i386-protos.h2
-rw-r--r--gcc/config/i386/i386.c73
-rw-r--r--gcc/config/i386/i386.md24
-rw-r--r--gcc/config/i386/predicates.md6
5 files changed, 72 insertions, 57 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a4c6e9e..f7e2572 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
@@ -23,9 +37,10 @@
* 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>
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 2002bfc..96971ae 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -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 *,
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index e095d98..742a34b 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -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)
/* 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;
}
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 299115d..049d534 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -5494,18 +5494,9 @@
{
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
@@ -5526,15 +5517,18 @@
/* 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>")))])
;; Add instructions
@@ -17832,7 +17826,7 @@
[(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"
@@ -17848,7 +17842,7 @@
}
[(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"
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 6cf5651..4e5c17d 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -813,6 +813,10 @@
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"
@@ -982,7 +986,7 @@
;; 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"