summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/config/i386/i386.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/config/i386/i386.c')
-rw-r--r--contrib/gcc/config/i386/i386.c241
1 files changed, 210 insertions, 31 deletions
diff --git a/contrib/gcc/config/i386/i386.c b/contrib/gcc/config/i386/i386.c
index bc3f456..f07ebad 100644
--- a/contrib/gcc/config/i386/i386.c
+++ b/contrib/gcc/config/i386/i386.c
@@ -457,7 +457,7 @@ static int const x86_64_int_return_registers[4] = {0 /*RAX*/, 1 /*RDI*/, 5, 4};
int const dbx64_register_map[FIRST_PSEUDO_REGISTER] =
{
0, 1, 2, 3, 4, 5, 6, 7, /* general regs */
- 33, 34, 35, 36, 37, 38, 39, 40 /* fp regs */
+ 33, 34, 35, 36, 37, 38, 39, 40, /* fp regs */
-1, -1, -1, -1, -1, /* arg, flags, fpsr, dir, frame */
17, 18, 19, 20, 21, 22, 23, 24, /* SSE */
41, 42, 43, 44, 45, 46, 47, 48, /* MMX */
@@ -1675,6 +1675,34 @@ classify_argument (mode, type, classes, bit_offset)
/* Classify each field of record and merge classes. */
if (TREE_CODE (type) == RECORD_TYPE)
{
+ /* For classes first merge in the field of the subclasses. */
+ if (TYPE_BINFO (type) != NULL && TYPE_BINFO_BASETYPES (type) != NULL)
+ {
+ tree bases = TYPE_BINFO_BASETYPES (type);
+ int n_bases = TREE_VEC_LENGTH (bases);
+ int i;
+
+ for (i = 0; i < n_bases; ++i)
+ {
+ tree binfo = TREE_VEC_ELT (bases, i);
+ int num;
+ int offset = tree_low_cst (BINFO_OFFSET (binfo), 0) * 8;
+ tree type = BINFO_TYPE (binfo);
+
+ num = classify_argument (TYPE_MODE (type),
+ type, subclasses,
+ (offset + bit_offset) % 256);
+ if (!num)
+ return 0;
+ for (i = 0; i < num; i++)
+ {
+ int pos = (offset + bit_offset) / 8 / 8;
+ classes[i + pos] =
+ merge_classes (subclasses[i], classes[i + pos]);
+ }
+ }
+ }
+ /* And now merge the fields of structure. */
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
{
if (TREE_CODE (field) == FIELD_DECL)
@@ -1735,6 +1763,33 @@ classify_argument (mode, type, classes, bit_offset)
else if (TREE_CODE (type) == UNION_TYPE
|| TREE_CODE (type) == QUAL_UNION_TYPE)
{
+ /* For classes first merge in the field of the subclasses. */
+ if (TYPE_BINFO (type) != NULL && TYPE_BINFO_BASETYPES (type) != NULL)
+ {
+ tree bases = TYPE_BINFO_BASETYPES (type);
+ int n_bases = TREE_VEC_LENGTH (bases);
+ int i;
+
+ for (i = 0; i < n_bases; ++i)
+ {
+ tree binfo = TREE_VEC_ELT (bases, i);
+ int num;
+ int offset = tree_low_cst (BINFO_OFFSET (binfo), 0) * 8;
+ tree type = BINFO_TYPE (binfo);
+
+ num = classify_argument (TYPE_MODE (type),
+ type, subclasses,
+ (offset + bit_offset) % 256);
+ if (!num)
+ return 0;
+ for (i = 0; i < num; i++)
+ {
+ int pos = (offset + bit_offset) / 8 / 8;
+ classes[i + pos] =
+ merge_classes (subclasses[i], classes[i + pos]);
+ }
+ }
+ }
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
{
if (TREE_CODE (field) == FIELD_DECL)
@@ -2841,6 +2896,18 @@ const_int_1_operand (op, mode)
return (GET_CODE (op) == CONST_INT && INTVAL (op) == 1);
}
+/* Return nonzero if OP is CONST_INT >= 1 and <= 31 (a valid operand
+ for shift & compare patterns, as shifting by 0 does not change flags),
+ else return zero. */
+
+int
+const_int_1_31_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ return (GET_CODE (op) == CONST_INT && INTVAL (op) >= 1 && INTVAL (op) <= 31);
+}
+
/* Returns 1 if OP is either a symbol reference or a sum of a symbol
reference and a constant. */
@@ -3863,9 +3930,6 @@ load_pic_register ()
emit_insn (gen_prologue_get_pc (pic_offset_table_rtx, pclab));
- if (! TARGET_DEEP_BRANCH_PREDICTION)
- emit_insn (gen_popsi1 (pic_offset_table_rtx));
-
emit_insn (gen_prologue_set_got (pic_offset_table_rtx, gotsym, pclab));
}
@@ -4015,8 +4079,9 @@ ix86_compute_frame_layout (frame)
offset += size;
- /* Add outgoing arguments area. */
- if (ACCUMULATE_OUTGOING_ARGS)
+ /* Add outgoing arguments area. Can be skipped if we eliminated
+ all the function calls as dead code. */
+ if (ACCUMULATE_OUTGOING_ARGS && !current_function_is_leaf)
{
offset += current_function_outgoing_args_size;
frame->outgoing_arguments_size = current_function_outgoing_args_size;
@@ -4024,9 +4089,13 @@ ix86_compute_frame_layout (frame)
else
frame->outgoing_arguments_size = 0;
- /* Align stack boundary. */
- frame->padding2 = ((offset + preferred_alignment - 1)
- & -preferred_alignment) - offset;
+ /* Align stack boundary. Only needed if we're calling another function
+ or using alloca. */
+ if (!current_function_is_leaf || current_function_calls_alloca)
+ frame->padding2 = ((offset + preferred_alignment - 1)
+ & -preferred_alignment) - offset;
+ else
+ frame->padding2 = 0;
offset += frame->padding2;
@@ -7958,7 +8027,12 @@ ix86_expand_int_movcc (operands)
if ((code == LEU || code == GTU)
&& GET_CODE (ix86_compare_op1) == CONST_INT
&& mode != HImode
- && (unsigned int) INTVAL (ix86_compare_op1) != 0xffffffff
+ && INTVAL (ix86_compare_op1) != -1
+ /* For x86-64, the immediate field in the instruction is 32-bit
+ signed, so we can't increment a DImode value above 0x7fffffff. */
+ && (!TARGET_64BIT
+ || GET_MODE (ix86_compare_op0) != DImode
+ || INTVAL (ix86_compare_op1) != 0x7fffffff)
&& GET_CODE (operands[2]) == CONST_INT
&& GET_CODE (operands[3]) == CONST_INT)
{
@@ -7966,7 +8040,8 @@ ix86_expand_int_movcc (operands)
code = LTU;
else
code = GEU;
- ix86_compare_op1 = GEN_INT (INTVAL (ix86_compare_op1) + 1);
+ ix86_compare_op1 = gen_int_mode (INTVAL (ix86_compare_op1) + 1,
+ GET_MODE (ix86_compare_op0));
}
start_sequence ();
@@ -9130,6 +9205,9 @@ ix86_expand_movstr (dst, src, count_exp, align_exp)
{
rtx countreg2;
rtx label = NULL;
+ int desired_alignment = (TARGET_PENTIUMPRO
+ && (count == 0 || count >= (unsigned int) 260)
+ ? 8 : UNITS_PER_WORD);
/* In case we don't know anything about the alignment, default to
library version, since it is usually equally fast and result in
@@ -9159,13 +9237,10 @@ ix86_expand_movstr (dst, src, count_exp, align_exp)
This is quite costy. Maybe we can revisit this decision later or
add some customizability to this code. */
- if (count == 0
- && align < (TARGET_PENTIUMPRO && (count == 0
- || count >= (unsigned int) 260)
- ? 8 : UNITS_PER_WORD))
+ if (count == 0 && align < desired_alignment)
{
label = gen_label_rtx ();
- emit_cmp_and_jump_insns (countreg, GEN_INT (UNITS_PER_WORD - 1),
+ emit_cmp_and_jump_insns (countreg, GEN_INT (desired_alignment - 1),
LEU, 0, counter_mode, 1, label);
}
if (align <= 1)
@@ -9184,10 +9259,7 @@ ix86_expand_movstr (dst, src, count_exp, align_exp)
emit_label (label);
LABEL_NUSES (label) = 1;
}
- if (align <= 4
- && ((TARGET_PENTIUMPRO && (count == 0
- || count >= (unsigned int) 260))
- || TARGET_64BIT))
+ if (align <= 4 && desired_alignment > 4)
{
rtx label = ix86_expand_aligntest (destreg, 4);
emit_insn (gen_strmovsi (destreg, srcreg));
@@ -9196,6 +9268,12 @@ ix86_expand_movstr (dst, src, count_exp, align_exp)
LABEL_NUSES (label) = 1;
}
+ if (label && desired_alignment > 4 && !TARGET_64BIT)
+ {
+ emit_label (label);
+ LABEL_NUSES (label) = 1;
+ label = NULL_RTX;
+ }
if (!TARGET_SINGLE_STRINGOP)
emit_insn (gen_cld ());
if (TARGET_64BIT)
@@ -9341,6 +9419,10 @@ ix86_expand_clrstr (src, count_exp, align_exp)
{
rtx countreg2;
rtx label = NULL;
+ /* Compute desired alignment of the string operation. */
+ int desired_alignment = (TARGET_PENTIUMPRO
+ && (count == 0 || count >= (unsigned int) 260)
+ ? 8 : UNITS_PER_WORD);
/* In case we don't know anything about the alignment, default to
library version, since it is usually equally fast and result in
@@ -9355,13 +9437,10 @@ ix86_expand_clrstr (src, count_exp, align_exp)
countreg = copy_to_mode_reg (counter_mode, count_exp);
zeroreg = copy_to_mode_reg (Pmode, const0_rtx);
- if (count == 0
- && align < (TARGET_PENTIUMPRO && (count == 0
- || count >= (unsigned int) 260)
- ? 8 : UNITS_PER_WORD))
+ if (count == 0 && align < desired_alignment)
{
label = gen_label_rtx ();
- emit_cmp_and_jump_insns (countreg, GEN_INT (UNITS_PER_WORD - 1),
+ emit_cmp_and_jump_insns (countreg, GEN_INT (desired_alignment - 1),
LEU, 0, counter_mode, 1, label);
}
if (align <= 1)
@@ -9382,8 +9461,7 @@ ix86_expand_clrstr (src, count_exp, align_exp)
emit_label (label);
LABEL_NUSES (label) = 1;
}
- if (align <= 4 && TARGET_PENTIUMPRO && (count == 0
- || count >= (unsigned int) 260))
+ if (align <= 4 && desired_alignment > 4)
{
rtx label = ix86_expand_aligntest (destreg, 4);
emit_insn (gen_strsetsi (destreg, (TARGET_64BIT
@@ -9394,6 +9472,13 @@ ix86_expand_clrstr (src, count_exp, align_exp)
LABEL_NUSES (label) = 1;
}
+ if (label && desired_alignment > 4 && !TARGET_64BIT)
+ {
+ emit_label (label);
+ LABEL_NUSES (label) = 1;
+ label = NULL_RTX;
+ }
+
if (!TARGET_SINGLE_STRINGOP)
emit_insn (gen_cld ());
if (TARGET_64BIT)
@@ -9409,18 +9494,18 @@ ix86_expand_clrstr (src, count_exp, align_exp)
emit_insn (gen_rep_stossi (destreg, countreg2, zeroreg,
destreg, countreg2));
}
-
if (label)
{
emit_label (label);
LABEL_NUSES (label) = 1;
}
+
if (TARGET_64BIT && align > 4 && count != 0 && (count & 4))
emit_insn (gen_strsetsi (destreg,
gen_rtx_SUBREG (SImode, zeroreg, 0)));
if (TARGET_64BIT && (align <= 4 || count == 0))
{
- rtx label = ix86_expand_aligntest (destreg, 2);
+ rtx label = ix86_expand_aligntest (countreg, 4);
emit_insn (gen_strsetsi (destreg,
gen_rtx_SUBREG (SImode, zeroreg, 0)));
emit_label (label);
@@ -9431,7 +9516,7 @@ ix86_expand_clrstr (src, count_exp, align_exp)
gen_rtx_SUBREG (HImode, zeroreg, 0)));
if (align <= 2 || count == 0)
{
- rtx label = ix86_expand_aligntest (destreg, 2);
+ rtx label = ix86_expand_aligntest (countreg, 2);
emit_insn (gen_strsethi (destreg,
gen_rtx_SUBREG (HImode, zeroreg, 0)));
emit_label (label);
@@ -9442,7 +9527,7 @@ ix86_expand_clrstr (src, count_exp, align_exp)
gen_rtx_SUBREG (QImode, zeroreg, 0)));
if (align <= 1 || count == 0)
{
- rtx label = ix86_expand_aligntest (destreg, 1);
+ rtx label = ix86_expand_aligntest (countreg, 1);
emit_insn (gen_strsetqi (destreg,
gen_rtx_SUBREG (QImode, zeroreg, 0)));
emit_label (label);
@@ -12473,3 +12558,97 @@ x86_order_regs_for_local_alloc ()
while (pos < FIRST_PSEUDO_REGISTER)
reg_alloc_order [pos++] = 0;
}
+
+void
+x86_output_mi_thunk (file, delta, function)
+ FILE *file;
+ int delta;
+ tree function;
+{
+ tree parm;
+ rtx xops[3];
+
+ if (ix86_regparm > 0)
+ parm = TYPE_ARG_TYPES (TREE_TYPE (function));
+ else
+ parm = NULL_TREE;
+ for (; parm; parm = TREE_CHAIN (parm))
+ if (TREE_VALUE (parm) == void_type_node)
+ break;
+
+ xops[0] = GEN_INT (delta);
+ if (TARGET_64BIT)
+ {
+ int n = aggregate_value_p (TREE_TYPE (TREE_TYPE (function))) != 0;
+ xops[1] = gen_rtx_REG (DImode, x86_64_int_parameter_registers[n]);
+ output_asm_insn ("add{q} {%0, %1|%1, %0}", xops);
+ if (flag_pic)
+ {
+ fprintf (file, "\tjmp *");
+ assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
+ fprintf (file, "@GOTPCREL(%%rip)\n");
+ }
+ else
+ {
+ fprintf (file, "\tjmp ");
+ assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
+ fprintf (file, "\n");
+ }
+ }
+ else
+ {
+ if (parm)
+ xops[1] = gen_rtx_REG (SImode, 0);
+ else if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function))))
+ xops[1] = gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 8));
+ else
+ xops[1] = gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 4));
+ output_asm_insn ("add{l} {%0, %1|%1, %0}", xops);
+
+ if (flag_pic)
+ {
+ xops[0] = pic_offset_table_rtx;
+ xops[1] = gen_label_rtx ();
+ xops[2] = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
+
+ if (ix86_regparm > 2)
+ abort ();
+ output_asm_insn ("push{l}\t%0", xops);
+ output_asm_insn ("call\t%P1", xops);
+ ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (xops[1]));
+ output_asm_insn ("pop{l}\t%0", xops);
+ output_asm_insn
+ ("add{l}\t{%2+[.-%P1], %0|%0, OFFSET FLAT: %2+[.-%P1]}", xops);
+ xops[0] = gen_rtx_MEM (SImode, XEXP (DECL_RTL (function), 0));
+ output_asm_insn
+ ("mov{l}\t{%0@GOT(%%ebx), %%ecx|%%ecx, %0@GOT[%%ebx]}", xops);
+ asm_fprintf (file, "\tpop{l\t%%ebx|\t%%ebx}\n");
+ asm_fprintf (file, "\tjmp\t{*%%ecx|%%ecx}\n");
+ }
+ else
+ {
+ fprintf (file, "\tjmp ");
+ assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
+ fprintf (file, "\n");
+ }
+ }
+}
+
+int
+x86_field_alignment (field, computed)
+ tree field;
+ int computed;
+{
+ enum machine_mode mode;
+ tree type = TREE_TYPE (field);
+
+ if (TARGET_64BIT || TARGET_ALIGN_DOUBLE)
+ return computed;
+ mode = TYPE_MODE (TREE_CODE (type) == ARRAY_TYPE
+ ? get_inner_array_type (type) : type);
+ if (mode == DFmode || mode == DCmode
+ || GET_MODE_CLASS (mode) == MODE_INT
+ || GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)
+ return MIN (32, computed);
+ return computed;
+}
OpenPOWER on IntegriCloud