diff options
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/gcc/config/i386/i386.c | 63 |
1 files changed, 43 insertions, 20 deletions
diff --git a/contrib/gcc/config/i386/i386.c b/contrib/gcc/config/i386/i386.c index 837a958..1103dec 100644 --- a/contrib/gcc/config/i386/i386.c +++ b/contrib/gcc/config/i386/i386.c @@ -296,25 +296,25 @@ struct processor_costs athlon_cost = { 8, /* "large" insn */ 9, /* MOVE_RATIO */ 4, /* cost for loading QImode using movzbl */ - {4, 5, 4}, /* cost of loading integer registers + {3, 4, 3}, /* cost of loading integer registers in QImode, HImode and SImode. Relative to reg-reg move (2). */ - {2, 3, 2}, /* cost of storing integer registers */ + {3, 4, 3}, /* cost of storing integer registers */ 4, /* cost of reg,reg fld/fst */ - {6, 6, 20}, /* cost of loading fp registers + {4, 4, 12}, /* cost of loading fp registers in SFmode, DFmode and XFmode */ - {4, 4, 16}, /* cost of loading integer registers */ + {6, 6, 8}, /* cost of loading integer registers */ 2, /* cost of moving MMX register */ - {2, 2}, /* cost of loading MMX registers + {4, 4}, /* cost of loading MMX registers in SImode and DImode */ - {2, 2}, /* cost of storing MMX registers + {4, 4}, /* cost of storing MMX registers in SImode and DImode */ 2, /* cost of moving SSE register */ - {2, 2, 8}, /* cost of loading SSE registers + {4, 4, 6}, /* cost of loading SSE registers in SImode, DImode and TImode */ - {2, 2, 8}, /* cost of storing SSE registers + {4, 4, 5}, /* cost of storing SSE registers in SImode, DImode and TImode */ - 6, /* MMX or SSE register to integer */ + 5, /* MMX or SSE register to integer */ 64, /* size of prefetch block */ 6, /* number of parallel prefetches */ }; @@ -1661,7 +1661,11 @@ classify_argument (mode, type, classes, bit_offset) { int bytes = (mode == BLKmode) ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode); - int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD; + int words = (bytes + (bit_offset % 64) / 8 + UNITS_PER_WORD - 1) / UNITS_PER_WORD; + + /* Variable sized structures are always passed on the stack. */ + if (mode == BLKmode && type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) + return 0; if (type && AGGREGATE_TYPE_P (type)) { @@ -3218,7 +3222,7 @@ q_regs_operand (op, mode) return 0; if (GET_CODE (op) == SUBREG) op = SUBREG_REG (op); - return QI_REG_P (op); + return ANY_QI_REG_P (op); } /* Return true if op is a NON_Q_REGS class register. */ @@ -6135,7 +6139,10 @@ print_operand_address (file, addr) int scale; if (! ix86_decompose_address (addr, &parts)) - abort (); + { + output_operand_lossage ("Wrong address expression or operand constraint"); + return; + } base = parts.base; index = parts.index; @@ -8249,7 +8256,7 @@ ix86_expand_int_movcc (operands) clob = gen_rtx_CLOBBER (VOIDmode, clob); tmp = gen_rtx_SET (VOIDmode, out, tmp); - tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob)); + tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, copy_rtx (tmp), clob)); emit_insn (tmp); } else @@ -12367,17 +12374,33 @@ ix86_register_move_cost (mode, class1, class2) enum reg_class class1, class2; { /* In case we require secondary memory, compute cost of the store followed - by load. In case of copying from general_purpose_register we may emit - multiple stores followed by single load causing memory size mismatch - stall. Count this as arbitarily high cost of 20. */ + by load. In order to avoid bad register allocation choices, we need + for this to be *at least* as high as the symmetric MEMORY_MOVE_COST. */ + if (ix86_secondary_memory_needed (class1, class2, mode, 0)) { - int add_cost = 0; + int cost = 1; + + cost += MAX (MEMORY_MOVE_COST (mode, class1, 0), + MEMORY_MOVE_COST (mode, class1, 1)); + cost += MAX (MEMORY_MOVE_COST (mode, class2, 0), + MEMORY_MOVE_COST (mode, class2, 1)); + + /* In case of copying from general_purpose_register we may emit multiple + stores followed by single load causing memory size mismatch stall. + Count this as arbitarily high cost of 20. */ if (CLASS_MAX_NREGS (class1, mode) > CLASS_MAX_NREGS (class2, mode)) - add_cost = 20; - return (MEMORY_MOVE_COST (mode, class1, 0) - + MEMORY_MOVE_COST (mode, class2, 1) + add_cost); + cost += 20; + + /* In the case of FP/MMX moves, the registers actually overlap, and we + have to switch modes in order to treat them differently. */ + if ((MMX_CLASS_P (class1) && MAYBE_FLOAT_CLASS_P (class2)) + || (MMX_CLASS_P (class2) && MAYBE_FLOAT_CLASS_P (class1))) + cost += 20; + + return cost; } + /* Moves between SSE/MMX and integer unit are expensive. */ if (MMX_CLASS_P (class1) != MMX_CLASS_P (class2) || SSE_CLASS_P (class1) != SSE_CLASS_P (class2)) |