diff options
-rw-r--r-- | gcc/ChangeLog | 29 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 65 | ||||
-rw-r--r-- | gcc/config/i386/i386.h | 34 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 35 |
4 files changed, 130 insertions, 33 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ccabd6f6f42..18f491a6dcb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,30 @@ +2016-06-07 Uros Bizjak <ubizjak@gmail.com> + + * config/i386/i386.h (enum ix86_enitity): Add X86_DIRFLAG. + (enum x86_dirflag_state): New enum. + (NUM_MODES_FOR_MODE_SWITCHING): Add X86_DIRFLAG_ANY. + (machine_function): Remove needs_cld. + (ix86_current_function_needs_cld): Remove. + * config/i386/i386.c (ix86_set_func_type): Set + ix86_optimize_mode_switching[X86_DIRFLAG] to 1. + (ix86_expand_prologue): Do not emit CLD here. + (ix86_dirflag_mode_needed): New function. + (ix86_dirflag_mode_entry): Ditto. + (ix86_mode_needed): Handle X86_DIRFLAG entity. + (ix86_mode_after): Ditto. + (ix86_mode_entry): Ditto. + (ix86_mode_exit): Ditto. + (ix86_emit_mode_set): Ditto. + * config/i386/i386.md (strmov_singleop): Set + ix86_optimize_mode_switching[X86_DIRFLAG] to 1 for TARGET_CLD. + Do not set ix86_current_function_needs_cld. + (rep_mov): Ditto. + (strset_singleop): Ditto. + (rep_stos): Ditto. + (cmpstrnqi_nz_1): Ditto. + (cmpstrnqi_1): Ditto. + (strlenqi_1): Ditto. + 2016-06-06 Jakub Jelinek <jakub@redhat.com> PR tree-optimization/71259 @@ -229,7 +256,7 @@ * config/ft32/ft32.c (ft32_setup_incoming_varargs, ft32_expand_prolog, ft32_expand_epilogue): - Handle pretend_args. + Handle pretend_args. * config/ft32/ft32.h: Remove OUTGOING_REG_PARM_STACK_SPACE. * config/ft32/ft32.md: Add pretend_returner. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index c191eebc09d..b807a9a0004 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -6823,6 +6823,8 @@ ix86_set_func_type (tree fndecl) cfun->machine->func_type = nargs == 2 ? TYPE_EXCEPTION : TYPE_INTERRUPT; + ix86_optimize_mode_switching[X86_DIRFLAG] = 1; + /* Only dwarf2out.c can handle -WORD(AP) as a pointer argument. */ if (write_symbols != NO_DEBUG && write_symbols != DWARF2_DEBUG) sorry ("Only DWARF debug format is supported for interrupt " @@ -13817,16 +13819,6 @@ ix86_expand_prologue (void) if (frame_pointer_needed && frame.red_zone_size) emit_insn (gen_memory_blockage ()); - /* Emit cld instruction if stringops are used in the function. Since - we can't assume the direction flag in interrupt handler, we must - emit cld instruction if stringops are used in interrupt handler or - interrupt handler isn't a leaf function. */ - if ((TARGET_CLD && ix86_current_function_needs_cld) - || (!TARGET_CLD - && cfun->machine->func_type != TYPE_NORMAL - && (ix86_current_function_needs_cld || !crtl->is_leaf))) - emit_insn (gen_cld ()); - /* SEH requires that the prologue end within 256 bytes of the start of the function. Prevent instruction schedules that would extend that. Further, prevent alloca modifications to the stack pointer from being @@ -18600,6 +18592,35 @@ output_387_binary_op (rtx insn, rtx *operands) return buf; } +/* Return needed mode for entity in optimize_mode_switching pass. */ + +static int +ix86_dirflag_mode_needed (rtx_insn *insn) +{ + if (CALL_P (insn)) + { + if (cfun->machine->func_type == TYPE_NORMAL) + return X86_DIRFLAG_ANY; + else + /* No need to emit CLD in interrupt handler for TARGET_CLD. */ + return TARGET_CLD ? X86_DIRFLAG_ANY : X86_DIRFLAG_RESET; + } + + if (recog_memoized (insn) < 0) + return X86_DIRFLAG_ANY; + + if (get_attr_type (insn) == TYPE_STR) + { + /* Emit cld instruction if stringops are used in the function. */ + if (cfun->machine->func_type == TYPE_NORMAL) + return TARGET_CLD ? X86_DIRFLAG_RESET : X86_DIRFLAG_ANY; + else + return X86_DIRFLAG_RESET; + } + + return X86_DIRFLAG_ANY; +} + /* Check if a 256bit AVX register is referenced inside of EXP. */ static bool @@ -18712,6 +18733,8 @@ ix86_mode_needed (int entity, rtx_insn *insn) { switch (entity) { + case X86_DIRFLAG: + return ix86_dirflag_mode_needed (insn); case AVX_U128: return ix86_avx_u128_mode_needed (insn); case I387_TRUNC: @@ -18771,6 +18794,8 @@ ix86_mode_after (int entity, int mode, rtx_insn *insn) { switch (entity) { + case X86_DIRFLAG: + return mode; case AVX_U128: return ix86_avx_u128_mode_after (mode, insn); case I387_TRUNC: @@ -18784,6 +18809,18 @@ ix86_mode_after (int entity, int mode, rtx_insn *insn) } static int +ix86_dirflag_mode_entry (void) +{ + /* For TARGET_CLD or in the interrupt handler we can't assume + direction flag state at function entry. */ + if (TARGET_CLD + || cfun->machine->func_type != TYPE_NORMAL) + return X86_DIRFLAG_ANY; + + return X86_DIRFLAG_RESET; +} + +static int ix86_avx_u128_mode_entry (void) { tree arg; @@ -18810,6 +18847,8 @@ ix86_mode_entry (int entity) { switch (entity) { + case X86_DIRFLAG: + return ix86_dirflag_mode_entry (); case AVX_U128: return ix86_avx_u128_mode_entry (); case I387_TRUNC: @@ -18843,6 +18882,8 @@ ix86_mode_exit (int entity) { switch (entity) { + case X86_DIRFLAG: + return X86_DIRFLAG_ANY; case AVX_U128: return ix86_avx_u128_mode_exit (); case I387_TRUNC: @@ -18986,6 +19027,10 @@ ix86_emit_mode_set (int entity, int mode, int prev_mode ATTRIBUTE_UNUSED, { switch (entity) { + case X86_DIRFLAG: + if (mode == X86_DIRFLAG_RESET) + emit_insn (gen_cld ()); + break; case AVX_U128: if (mode == AVX_U128_CLEAN) ix86_avx_emit_vzeroupper (regs_live); diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index f1fa02c3302..cab0a5d013b 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -2376,9 +2376,21 @@ enum ix86_fpcmp_strategy { Post-reload pass may be later used to eliminate the redundant fildcw if needed. */ +enum ix86_stack_slot +{ + SLOT_TEMP = 0, + SLOT_CW_STORED, + SLOT_CW_TRUNC, + SLOT_CW_FLOOR, + SLOT_CW_CEIL, + SLOT_CW_MASK_PM, + MAX_386_STACK_LOCALS +}; + enum ix86_entity { - AVX_U128 = 0, + X86_DIRFLAG = 0, + AVX_U128, I387_TRUNC, I387_FLOOR, I387_CEIL, @@ -2386,15 +2398,10 @@ enum ix86_entity MAX_386_ENTITIES }; -enum ix86_stack_slot +enum x86_dirflag_state { - SLOT_TEMP = 0, - SLOT_CW_STORED, - SLOT_CW_TRUNC, - SLOT_CW_FLOOR, - SLOT_CW_CEIL, - SLOT_CW_MASK_PM, - MAX_386_STACK_LOCALS + X86_DIRFLAG_RESET, + X86_DIRFLAG_ANY }; enum avx_u128_state @@ -2418,8 +2425,9 @@ enum avx_u128_state starting counting at zero - determines the integer that is used to refer to the mode-switched entity in question. */ -#define NUM_MODES_FOR_MODE_SWITCHING \ - { AVX_U128_ANY, I387_CW_ANY, I387_CW_ANY, I387_CW_ANY, I387_CW_ANY } +#define NUM_MODES_FOR_MODE_SWITCHING \ + { X86_DIRFLAG_ANY, AVX_U128_ANY, \ + I387_CW_ANY, I387_CW_ANY, I387_CW_ANY, I387_CW_ANY } /* Avoid renaming of stack registers, as doing so in combination with @@ -2516,9 +2524,6 @@ struct GTY(()) machine_function { /* Nonzero if the function accesses a previous frame. */ BOOL_BITFIELD accesses_prev_frame : 1; - /* Nonzero if the function requires a CLD in the prologue. */ - BOOL_BITFIELD needs_cld : 1; - /* Set by ix86_compute_frame_layout and used by prologue/epilogue expander to determine the style used. */ BOOL_BITFIELD use_fast_prologue_epilogue : 1; @@ -2572,7 +2577,6 @@ struct GTY(()) machine_function { #define ix86_varargs_gpr_size (cfun->machine->varargs_gpr_size) #define ix86_varargs_fpr_size (cfun->machine->varargs_fpr_size) #define ix86_optimize_mode_switching (cfun->machine->optimize_mode_switching) -#define ix86_current_function_needs_cld (cfun->machine->needs_cld) #define ix86_pc_thunk_call_expanded (cfun->machine->pc_thunk_call_expanded) #define ix86_tls_descriptor_calls_expanded_in_cfun \ (cfun->machine->tls_descriptor_call_expanded_p) diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index a32c4e204ce..416cdcd9129 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -16350,7 +16350,10 @@ (set (match_operand 2 "register_operand") (match_operand 5))])] "" - "ix86_current_function_needs_cld = 1;") +{ + if (TARGET_CLD) + ix86_optimize_mode_switching[X86_DIRFLAG] = 1; +}) (define_insn "*strmovdi_rex_1" [(set (mem:DI (match_operand:P 2 "register_operand" "0")) @@ -16432,7 +16435,10 @@ (match_operand 3 "memory_operand")) (use (match_dup 4))])] "" - "ix86_current_function_needs_cld = 1;") +{ + if (TARGET_CLD) + ix86_optimize_mode_switching[X86_DIRFLAG] = 1; +}) (define_insn "*rep_movdi_rex64" [(set (match_operand:P 2 "register_operand" "=c") (const_int 0)) @@ -16555,7 +16561,10 @@ (match_operand 3)) (unspec [(const_int 0)] UNSPEC_STOS)])] "" - "ix86_current_function_needs_cld = 1;") +{ + if (TARGET_CLD) + ix86_optimize_mode_switching[X86_DIRFLAG] = 1; +}) (define_insn "*strsetdi_rex_1" [(set (mem:DI (match_operand:P 1 "register_operand" "0")) @@ -16627,7 +16636,10 @@ (use (match_operand 3 "register_operand")) (use (match_dup 1))])] "" - "ix86_current_function_needs_cld = 1;") +{ + if (TARGET_CLD) + ix86_optimize_mode_switching[X86_DIRFLAG] = 1; +}) (define_insn "*rep_stosdi_rex64" [(set (match_operand:P 1 "register_operand" "=c") (const_int 0)) @@ -16786,7 +16798,10 @@ (clobber (match_operand 1 "register_operand")) (clobber (match_dup 2))])] "" - "ix86_current_function_needs_cld = 1;") +{ + if (TARGET_CLD) + ix86_optimize_mode_switching[X86_DIRFLAG] = 1; +}) (define_insn "*cmpstrnqi_nz_1" [(set (reg:CC FLAGS_REG) @@ -16824,7 +16839,10 @@ (clobber (match_operand 1 "register_operand")) (clobber (match_dup 2))])] "" - "ix86_current_function_needs_cld = 1;") +{ + if (TARGET_CLD) + ix86_optimize_mode_switching[X86_DIRFLAG] = 1; +}) (define_insn "*cmpstrnqi_1" [(set (reg:CC FLAGS_REG) @@ -16870,7 +16888,10 @@ (clobber (match_operand 1 "register_operand")) (clobber (reg:CC FLAGS_REG))])] "" - "ix86_current_function_needs_cld = 1;") +{ + if (TARGET_CLD) + ix86_optimize_mode_switching[X86_DIRFLAG] = 1; +}) (define_insn "*strlenqi_1" [(set (match_operand:P 0 "register_operand" "=&c") |