diff options
author | Uros Bizjak <uros@gcc.gnu.org> | 2012-10-22 00:12:46 +0200 |
---|---|---|
committer | Uros Bizjak <uros@gcc.gnu.org> | 2012-10-22 00:12:46 +0200 |
commit | cab54dfa3ad330dd2ccb876e85112cc4363786d5 (patch) | |
tree | b7154eb94cb5fcc8262e1ed94e79ec04396f1824 /gcc | |
parent | 84cac7eff72290d1b2a57c75df602a02ffd2f56e (diff) | |
download | gcc-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/ChangeLog | 24 | ||||
-rw-r--r-- | gcc/config/i386/i386-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 73 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 24 | ||||
-rw-r--r-- | gcc/config/i386/predicates.md | 6 |
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" |