On Fri, Mar 30, 2012 at 8:19 AM, Richard Henderson <r...@redhat.com> wrote: > On 03/30/2012 11:11 AM, Richard Henderson wrote: >> On 03/30/2012 11:03 AM, Teresa Johnson wrote: >>> +(define_insn "*movhi_imm_internal" >>> + [(set (match_operand:HI 0 "memory_operand" "=m") >>> + (match_operand:HI 1 "immediate_operand" "n"))] >>> + "!TARGET_LCP_STALL" >>> +{ >>> + return "mov{w}\t{%1, %0|%0, %1}"; >>> +} >>> + [(set (attr "type") (const_string "imov")) >>> + (set (attr "mode") (const_string "HI"))]) >>> + >>> (define_insn "*movhi_internal" >>> [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m") >>> - (match_operand:HI 1 "general_operand" "r,rn,rm,rn"))] >>> + (match_operand:HI 1 "general_operand" "r,rn,rm,r"))] >>> "!(MEM_P (operands[0]) && MEM_P (operands[1]))" >> >> For reload to work correctly, all alternatives must remain part of the same >> pattern. >> This issue should be handled with the ISA and ENABLED attributes. > > I'll also ask if this should better be handled with a peephole2. > > While movw $1234,(%eax) might be expensive, is it so expensive that we > *must* force the use of a free register? Might it be better only to > split the insn in two if and only if a free register exists? > > That can easily be done with a peephole2 pattern... >
Here is a very old LCP patch with peephole2. It may need some updates. -- H.J.
--- gcc/config/i386/i386-tune.c.movw 2007-08-06 07:58:38.000000000 -0700 +++ gcc/config/i386/i386-tune.c 2007-08-06 07:58:38.000000000 -0700 @@ -117,6 +117,9 @@ x86_tune_options (void) abort (); } } + + if (x86_split_movw_length_string) + x86_split_movw_length = atoi (x86_split_movw_length_string); } #undef TARGET_SCHED_ISSUE_RATE @@ -137,3 +140,4 @@ const char *ix86_adjust_cost_string; int ia32_multipass_dfa_lookahead_value; const char *ia32_multipass_dfa_lookahead_string; +int x86_split_movw_length; --- gcc/config/i386/i386-tune.h.movw 2007-08-06 07:58:38.000000000 -0700 +++ gcc/config/i386/i386-tune.h 2007-08-06 07:58:38.000000000 -0700 @@ -4,6 +4,9 @@ -mno-default + -msplit-movw-length=NUMBER + NUMBER is the maximum 16bit immediate move instruction length + -missue-rate=NUMBER -madjust-cost=NUMBER @@ -72,6 +75,7 @@ extern void x86_tune_options (void); +extern int x86_split_movw_length; extern int ix86_issue_rate_value; extern const char *ix86_issue_rate_string; --- gcc/config/i386/i386-tune.opt.movw 2007-08-06 07:58:38.000000000 -0700 +++ gcc/config/i386/i386-tune.opt 2007-08-06 07:58:38.000000000 -0700 @@ -363,3 +363,6 @@ Target RejectNegative Joined Report Var( mno-default Target RejectNegative Report Var(x86_no_default_string) Undocumented +msplit-movw-length= +Target RejectNegative Joined Report Var(x86_split_movw_length_string) Undocumented + --- gcc/config/i386/i386.md.movw 2007-08-06 07:55:01.000000000 -0700 +++ gcc/config/i386/i386.md 2007-08-06 08:50:48.000000000 -0700 @@ -19655,14 +19655,18 @@ (set (match_dup 0) (match_dup 1))] "") +;; Also don't move a 16bit immediate directly to memory when target +;; has slow LCP instructions. (define_peephole2 [(match_scratch:HI 1 "r") (set (match_operand:HI 0 "memory_operand" "") (const_int 0))] "optimize_insn_for_speed_p () - && ! TARGET_USE_MOV0 - && TARGET_SPLIT_LONG_MOVES - && get_attr_length (insn) >= ix86_cur_cost ()->large_insn + && ((x86_split_movw_length_string != NULL + && get_attr_length (insn) >= x86_split_movw_length) + || (! TARGET_USE_MOV0 + && TARGET_SPLIT_LONG_MOVES + && get_attr_length (insn) >= ix86_cur_cost ()->large_insn)) && peep2_regno_dead_p (0, FLAGS_REG)" [(parallel [(set (match_dup 2) (const_int 0)) (clobber (reg:CC FLAGS_REG))]) @@ -19694,13 +19698,17 @@ (set (match_dup 0) (match_dup 2))] "") +;; Also don't move a 16bit immediate directly to memory when target +;; has slow LCP instructions. (define_peephole2 [(match_scratch:HI 2 "r") (set (match_operand:HI 0 "memory_operand" "") (match_operand:HI 1 "immediate_operand" ""))] "optimize_insn_for_speed_p () - && TARGET_SPLIT_LONG_MOVES - && get_attr_length (insn) >= ix86_cur_cost ()->large_insn" + && ((x86_split_movw_length_string != NULL + && get_attr_length (insn) >= x86_split_movw_length) + || (TARGET_SPLIT_LONG_MOVES + && get_attr_length (insn) >= ix86_cur_cost ()->large_insn))" [(set (match_dup 2) (match_dup 1)) (set (match_dup 0) (match_dup 2))] "")