diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 99ea21e0e14..5a23b03dd39 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +2010-08-30 Uros Bizjak + + * config/i386/i386.md (zero_extendsidi2_1): Rename from + zero_extendsidi2_32. + (zero_extenddi2): Macroize insn from zero_extend{qi,hi}di2 + using SWI12 mode iterator. + (zero_extendhisi2_and): Merge insn pattern and corresponding spliter + to define_insn_and_split pattern. + (zero_extendqi2): Macroize expander from zero_extendqi{hi,si}2 + using SWI24 mode iterator. + (*zero_extendqi2_and): Macroize insn from + *zero_extendqi{hi,si}2_and using SWI24 mode iterator. + (*zero_extendqi2_movzbl_and): Macroize insn from + *zero_extendqihi2_movzbw_and and *zero_extendqisi2_movzbl_and using + SWI24 mode iterator. + (*zero_extendqi2_movzbl): Ditto from + *zero_extendqi{hi,si}2_movzbl. + (extendsidi2_1): Rename from extendsidi2_32. + (extenddi2): Macroize insn from extend{qi,hi}di2 using + SWI12 mode iterator. + 2010-08-29 Eric Botcazou * config/ia64/ia64.h (HARD_REGNO_NREGS): Return 1 for CCImode in diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 4d4e4c9c992..2f288733f98 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -3587,211 +3587,44 @@ ;; Zero extension instructions -(define_expand "zero_extendhisi2" - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] - "" -{ - if (TARGET_ZERO_EXTEND_WITH_AND && optimize_function_for_speed_p (cfun)) - { - operands[1] = force_reg (HImode, operands[1]); - emit_insn (gen_zero_extendhisi2_and (operands[0], operands[1])); - DONE; - } -}) - -(define_insn "zero_extendhisi2_and" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extend:SI (match_operand:HI 1 "register_operand" "0"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_ZERO_EXTEND_WITH_AND && optimize_function_for_speed_p (cfun)" - "#" - [(set_attr "type" "alu1") - (set_attr "mode" "SI")]) - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:HI 1 "register_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "reload_completed && TARGET_ZERO_EXTEND_WITH_AND - && optimize_function_for_speed_p (cfun)" - [(parallel [(set (match_dup 0) (and:SI (match_dup 0) (const_int 65535))) - (clobber (reg:CC FLAGS_REG))])] - "") - -(define_insn "*zero_extendhisi2_movzwl" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))] - "!TARGET_ZERO_EXTEND_WITH_AND - || optimize_function_for_size_p (cfun)" - "movz{wl|x}\t{%1, %0|%0, %1}" - [(set_attr "type" "imovx") - (set_attr "mode" "SI")]) - -(define_expand "zero_extendqihi2" - [(parallel - [(set (match_operand:HI 0 "register_operand" "") - (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" ""))) - (clobber (reg:CC FLAGS_REG))])] - "" - "") - -(define_insn "*zero_extendqihi2_and" - [(set (match_operand:HI 0 "register_operand" "=r,?&q") - (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0,qm"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_ZERO_EXTEND_WITH_AND && optimize_function_for_speed_p (cfun)" - "#" - [(set_attr "type" "alu1") - (set_attr "mode" "HI")]) - -(define_insn "*zero_extendqihi2_movzbw_and" - [(set (match_operand:HI 0 "register_operand" "=r,r") - (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "qm,0"))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_ZERO_EXTEND_WITH_AND || optimize_function_for_size_p (cfun)" - "#" - [(set_attr "type" "imovx,alu1") - (set_attr "mode" "HI")]) - -; zero extend to SImode here to avoid partial register stalls -(define_insn "*zero_extendqihi2_movzbl" - [(set (match_operand:HI 0 "register_operand" "=r") - (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "qm")))] - "(!TARGET_ZERO_EXTEND_WITH_AND || optimize_function_for_size_p (cfun)) - && reload_completed" - "movz{bl|x}\t{%1, %k0|%k0, %1}" - [(set_attr "type" "imovx") - (set_attr "mode" "SI")]) - -;; For the movzbw case strip only the clobber -(define_split - [(set (match_operand:HI 0 "register_operand" "") - (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "reload_completed - && (!TARGET_ZERO_EXTEND_WITH_AND - || optimize_function_for_size_p (cfun)) - && (!REG_P (operands[1]) || ANY_QI_REG_P (operands[1]))" - [(set (match_operand:HI 0 "register_operand" "") - (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))]) - -;; When source and destination does not overlap, clear destination -;; first and then do the movb -(define_split - [(set (match_operand:HI 0 "register_operand" "") - (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "reload_completed - && ANY_QI_REG_P (operands[0]) - && (TARGET_ZERO_EXTEND_WITH_AND - && optimize_function_for_speed_p (cfun)) - && !reg_overlap_mentioned_p (operands[0], operands[1])" - [(set (strict_low_part (match_dup 2)) (match_dup 1))] -{ - operands[2] = gen_lowpart (QImode, operands[0]); - ix86_expand_clear (operands[0]); -}) - -;; Rest is handled by single and. -(define_split - [(set (match_operand:HI 0 "register_operand" "") - (zero_extend:HI (match_operand:QI 1 "register_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "reload_completed - && true_regnum (operands[0]) == true_regnum (operands[1])" - [(parallel [(set (match_dup 0) (and:HI (match_dup 0) (const_int 255))) - (clobber (reg:CC FLAGS_REG))])] - "") - -(define_expand "zero_extendqisi2" - [(parallel - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" ""))) - (clobber (reg:CC FLAGS_REG))])] - "" - "") - -(define_insn "*zero_extendqisi2_and" - [(set (match_operand:SI 0 "register_operand" "=r,?&q") - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,qm"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_ZERO_EXTEND_WITH_AND && optimize_function_for_speed_p (cfun)" - "#" - [(set_attr "type" "alu1") - (set_attr "mode" "SI")]) - -(define_insn "*zero_extendqisi2_movzbl_and" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm,0"))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_ZERO_EXTEND_WITH_AND || optimize_function_for_size_p (cfun)" - "#" - [(set_attr "type" "imovx,alu1") - (set_attr "mode" "SI")]) - -(define_insn "*zero_extendqisi2_movzbl" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")))] - "(!TARGET_ZERO_EXTEND_WITH_AND || optimize_function_for_size_p (cfun)) - && reload_completed" - "movz{bl|x}\t{%1, %0|%0, %1}" - [(set_attr "type" "imovx") - (set_attr "mode" "SI")]) - -;; For the movzbl case strip only the clobber -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "reload_completed - && (!TARGET_ZERO_EXTEND_WITH_AND || optimize_function_for_size_p (cfun)) - && (!REG_P (operands[1]) || ANY_QI_REG_P (operands[1]))" - [(set (match_dup 0) - (zero_extend:SI (match_dup 1)))]) - -;; When source and destination does not overlap, clear destination -;; first and then do the movb -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "reload_completed - && ANY_QI_REG_P (operands[0]) - && (ANY_QI_REG_P (operands[1]) || MEM_P (operands[1])) - && (TARGET_ZERO_EXTEND_WITH_AND && optimize_function_for_speed_p (cfun)) - && !reg_overlap_mentioned_p (operands[0], operands[1])" - [(set (strict_low_part (match_dup 2)) (match_dup 1))] -{ - operands[2] = gen_lowpart (QImode, operands[0]); - ix86_expand_clear (operands[0]); -}) - -;; Rest is handled by single and. -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:QI 1 "register_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "reload_completed - && true_regnum (operands[0]) == true_regnum (operands[1])" - [(parallel [(set (match_dup 0) (and:SI (match_dup 0) (const_int 255))) - (clobber (reg:CC FLAGS_REG))])] - "") - -;; %%% Kill me once multi-word ops are sane. (define_expand "zero_extendsidi2" - [(set (match_operand:DI 0 "register_operand" "") - (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "")))] + [(set (match_operand:DI 0 "nonimmediate_operand" "") + (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "")))] "" { if (!TARGET_64BIT) { - emit_insn (gen_zero_extendsidi2_32 (operands[0], operands[1])); + emit_insn (gen_zero_extendsidi2_1 (operands[0], operands[1])); DONE; } }) -(define_insn "zero_extendsidi2_32" +(define_insn "*zero_extendsidi2_rex64" + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o,?*Ym,?*y,?*Yi,*Y2") + (zero_extend:DI + (match_operand:SI 1 "nonimmediate_operand" "rm,0,r ,m ,r ,m")))] + "TARGET_64BIT" + "@ + mov\t{%k1, %k0|%k0, %k1} + # + movd\t{%1, %0|%0, %1} + movd\t{%1, %0|%0, %1} + %vmovd\t{%1, %0|%0, %1} + %vmovd\t{%1, %0|%0, %1}" + [(set_attr "type" "imovx,imov,mmxmov,mmxmov,ssemov,ssemov") + (set_attr "prefix" "orig,*,orig,orig,maybe_vex,maybe_vex") + (set_attr "prefix_0f" "0,*,*,*,*,*") + (set_attr "mode" "SI,DI,DI,DI,TI,TI")]) + +(define_split + [(set (match_operand:DI 0 "memory_operand" "") + (zero_extend:DI (match_dup 0)))] + "TARGET_64BIT" + [(set (match_dup 4) (const_int 0))] + "split_di (&operands[0], 1, &operands[3], &operands[4]);") + +;; %%% Kill me once multi-word ops are sane. +(define_insn "zero_extendsidi2_1" [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?o,?*Ym,?*y,?*Yi,*Y2") (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "0,rm,r ,r ,m ,r ,m"))) @@ -3809,30 +3642,6 @@ (set_attr "prefix" "*,*,*,orig,orig,maybe_vex,maybe_vex") (set_attr "mode" "SI,SI,SI,DI,DI,TI,TI")]) -(define_insn "zero_extendsidi2_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o,?*Ym,?*y,?*Yi,*Y2") - (zero_extend:DI - (match_operand:SI 1 "nonimmediate_operand" "rm,0,r ,m ,r ,m")))] - "TARGET_64BIT" - "@ - mov\t{%k1, %k0|%k0, %k1} - # - movd\t{%1, %0|%0, %1} - movd\t{%1, %0|%0, %1} - %vmovd\t{%1, %0|%0, %1} - %vmovd\t{%1, %0|%0, %1}" - [(set_attr "type" "imovx,imov,mmxmov,mmxmov,ssemov,ssemov") - (set_attr "prefix" "orig,*,orig,orig,maybe_vex,maybe_vex") - (set_attr "prefix_0f" "0,*,*,*,*,*") - (set_attr "mode" "SI,DI,DI,DI,TI,TI")]) - -(define_split - [(set (match_operand:DI 0 "memory_operand" "") - (zero_extend:DI (match_dup 0)))] - "TARGET_64BIT" - [(set (match_dup 4) (const_int 0))] - "split_di (&operands[0], 1, &operands[3], &operands[4]);") - (define_split [(set (match_operand:DI 0 "register_operand" "") (zero_extend:DI (match_operand:SI 1 "register_operand" ""))) @@ -3852,47 +3661,140 @@ (set (match_dup 4) (const_int 0))] "split_di (&operands[0], 1, &operands[3], &operands[4]);") -(define_insn "zero_extendhidi2" +(define_insn "zero_extenddi2" [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "rm")))] + (zero_extend:DI + (match_operand:SWI12 1 "nonimmediate_operand" "m")))] "TARGET_64BIT" - "movz{wl|x}\t{%1, %k0|%k0, %1}" + "movz{l|x}\t{%1, %k0|%k0, %1}" [(set_attr "type" "imovx") (set_attr "mode" "SI")]) -(define_insn "zero_extendqidi2" - [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "rm")))] - "TARGET_64BIT" - "movz{bl|x}\t{%1, %k0|%k0, %1}" - [(set_attr "type" "imovx") - (set_attr "mode" "SI")]) - -;; Sign extension instructions - -(define_expand "extendsidi2" - [(parallel [(set (match_operand:DI 0 "register_operand" "") - (sign_extend:DI (match_operand:SI 1 "register_operand" ""))) - (clobber (reg:CC FLAGS_REG)) - (clobber (match_scratch:SI 2 ""))])] +(define_expand "zero_extendhisi2" + [(set (match_operand:SI 0 "register_operand" "") + (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] "" { - if (TARGET_64BIT) + if (TARGET_ZERO_EXTEND_WITH_AND && optimize_function_for_speed_p (cfun)) { - emit_insn (gen_extendsidi2_rex64 (operands[0], operands[1])); + operands[1] = force_reg (HImode, operands[1]); + emit_insn (gen_zero_extendhisi2_and (operands[0], operands[1])); DONE; } }) -(define_insn "*extendsidi2_1" - [(set (match_operand:DI 0 "nonimmediate_operand" "=*A,r,?r,?*o") - (sign_extend:DI (match_operand:SI 1 "register_operand" "0,0,r,r"))) - (clobber (reg:CC FLAGS_REG)) - (clobber (match_scratch:SI 2 "=X,X,X,&r"))] - "!TARGET_64BIT" - "#") +(define_insn_and_split "zero_extendhisi2_and" + [(set (match_operand:SI 0 "register_operand" "=r") + (zero_extend:SI (match_operand:HI 1 "register_operand" "0"))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_ZERO_EXTEND_WITH_AND && optimize_function_for_speed_p (cfun)" + "#" + "&& reload_completed" + [(parallel [(set (match_dup 0) (and:SI (match_dup 0) (const_int 65535))) + (clobber (reg:CC FLAGS_REG))])] + "" + [(set_attr "type" "alu1") + (set_attr "mode" "SI")]) -(define_insn "extendsidi2_rex64" +(define_insn "*zero_extendhisi2_movzwl" + [(set (match_operand:SI 0 "register_operand" "=r") + (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))] + "!TARGET_ZERO_EXTEND_WITH_AND + || optimize_function_for_size_p (cfun)" + "movz{wl|x}\t{%1, %0|%0, %1}" + [(set_attr "type" "imovx") + (set_attr "mode" "SI")]) + +(define_expand "zero_extendqi2" + [(parallel + [(set (match_operand:SWI24 0 "register_operand" "") + (zero_extend:SWI24 (match_operand:QI 1 "nonimmediate_operand" ""))) + (clobber (reg:CC FLAGS_REG))])] + "" + "") + +(define_insn "*zero_extendqi2_and" + [(set (match_operand:SWI24 0 "register_operand" "=r,?&q") + (zero_extend:SWI24 (match_operand:QI 1 "nonimmediate_operand" "0,qm"))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_ZERO_EXTEND_WITH_AND && optimize_function_for_speed_p (cfun)" + "#" + [(set_attr "type" "alu1") + (set_attr "mode" "")]) + +;; When source and destination does not overlap, clear destination +;; first and then do the movb +(define_split + [(set (match_operand:SWI24 0 "register_operand" "") + (zero_extend:SWI24 (match_operand:QI 1 "nonimmediate_operand" ""))) + (clobber (reg:CC FLAGS_REG))] + "reload_completed + && (TARGET_ZERO_EXTEND_WITH_AND && optimize_function_for_speed_p (cfun)) + && ANY_QI_REG_P (operands[0]) + && (ANY_QI_REG_P (operands[1]) || MEM_P (operands[1])) + && !reg_overlap_mentioned_p (operands[0], operands[1])" + [(set (strict_low_part (match_dup 2)) (match_dup 1))] +{ + operands[2] = gen_lowpart (QImode, operands[0]); + ix86_expand_clear (operands[0]); +}) + +(define_insn "*zero_extendqi2_movzbl_and" + [(set (match_operand:SWI24 0 "register_operand" "=r,r") + (zero_extend:SWI24 (match_operand:QI 1 "nonimmediate_operand" "qm,0"))) + (clobber (reg:CC FLAGS_REG))] + "!TARGET_ZERO_EXTEND_WITH_AND || optimize_function_for_size_p (cfun)" + "#" + [(set_attr "type" "imovx,alu1") + (set_attr "mode" "")]) + +;; For the movzbl case strip only the clobber +(define_split + [(set (match_operand:SWI24 0 "register_operand" "") + (zero_extend:SWI24 (match_operand:QI 1 "nonimmediate_operand" ""))) + (clobber (reg:CC FLAGS_REG))] + "reload_completed + && (!TARGET_ZERO_EXTEND_WITH_AND || optimize_function_for_size_p (cfun)) + && (!REG_P (operands[1]) || ANY_QI_REG_P (operands[1]))" + [(set (match_dup 0) + (zero_extend:SWI24 (match_dup 1)))]) + +; zero extend to SImode to avoid partial register stalls +(define_insn "*zero_extendqi2_movzbl" + [(set (match_operand:SWI24 0 "register_operand" "=r") + (zero_extend:SWI24 (match_operand:QI 1 "nonimmediate_operand" "qm")))] + "reload_completed + && (!TARGET_ZERO_EXTEND_WITH_AND || optimize_function_for_size_p (cfun))" + "movz{bl|x}\t{%1, %k0|%k0, %1}" + [(set_attr "type" "imovx") + (set_attr "mode" "SI")]) + +;; Rest is handled by single and. +(define_split + [(set (match_operand:SWI24 0 "register_operand" "") + (zero_extend:SWI24 (match_operand:QI 1 "register_operand" ""))) + (clobber (reg:CC FLAGS_REG))] + "reload_completed + && true_regnum (operands[0]) == true_regnum (operands[1])" + [(parallel [(set (match_dup 0) (and:SWI24 (match_dup 0) (const_int 255))) + (clobber (reg:CC FLAGS_REG))])] + "") + +;; Sign extension instructions + +(define_expand "extendsidi2" + [(set (match_operand:DI 0 "register_operand" "") + (sign_extend:DI (match_operand:SI 1 "register_operand" "")))] + "" +{ + if (!TARGET_64BIT) + { + emit_insn (gen_extendsidi2_1 (operands[0], operands[1])); + DONE; + } +}) + +(define_insn "*extendsidi2_rex64" [(set (match_operand:DI 0 "register_operand" "=*a,r") (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "*0,rm")))] "TARGET_64BIT" @@ -3904,21 +3806,13 @@ (set_attr "prefix_0f" "0") (set_attr "modrm" "0,1")]) -(define_insn "extendhidi2" - [(set (match_operand:DI 0 "register_operand" "=r") - (sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "rm")))] - "TARGET_64BIT" - "movs{wq|x}\t{%1, %0|%0, %1}" - [(set_attr "type" "imovx") - (set_attr "mode" "DI")]) - -(define_insn "extendqidi2" - [(set (match_operand:DI 0 "register_operand" "=r") - (sign_extend:DI (match_operand:QI 1 "nonimmediate_operand" "qm")))] - "TARGET_64BIT" - "movs{bq|x}\t{%1, %0|%0, %1}" - [(set_attr "type" "imovx") - (set_attr "mode" "DI")]) +(define_insn "extendsidi2_1" + [(set (match_operand:DI 0 "nonimmediate_operand" "=*A,r,?r,?*o") + (sign_extend:DI (match_operand:SI 1 "register_operand" "0,0,r,r"))) + (clobber (reg:CC FLAGS_REG)) + (clobber (match_scratch:SI 2 "=X,X,X,&r"))] + "!TARGET_64BIT" + "#") ;; Extend to memory case when source register does die. (define_split @@ -3995,6 +3889,15 @@ DONE; }) +(define_insn "extenddi2" + [(set (match_operand:DI 0 "register_operand" "=r") + (sign_extend:DI + (match_operand:SWI12 1 "nonimmediate_operand" "m")))] + "TARGET_64BIT" + "movs{q|x}\t{%1, %0|%0, %1}" + [(set_attr "type" "imovx") + (set_attr "mode" "DI")]) + (define_insn "extendhisi2" [(set (match_operand:SI 0 "register_operand" "=*a,r") (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "*0,rm")))] @@ -4024,7 +3927,8 @@ (define_insn "*extendhisi2_zext" [(set (match_operand:DI 0 "register_operand" "=*a,r") (zero_extend:DI - (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "*0,rm"))))] + (sign_extend:SI + (match_operand:HI 1 "nonimmediate_operand" "*0,rm"))))] "TARGET_64BIT" { switch (get_attr_prefix_0f (insn)) @@ -4048,32 +3952,6 @@ (const_string "0") (const_string "1")))]) -(define_insn "extendqihi2" - [(set (match_operand:HI 0 "register_operand" "=*a,r") - (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "*0,qm")))] - "" -{ - switch (get_attr_prefix_0f (insn)) - { - case 0: - return "{cbtw|cbw}"; - default: - return "movs{bw|x}\t{%1, %0|%0, %1}"; - } -} - [(set_attr "type" "imovx") - (set_attr "mode" "HI") - (set (attr "prefix_0f") - ;; movsx is short decodable while cwtl is vector decoded. - (if_then_else (and (eq_attr "cpu" "!k6") - (eq_attr "alternative" "0")) - (const_string "0") - (const_string "1"))) - (set (attr "modrm") - (if_then_else (eq_attr "prefix_0f" "0") - (const_string "0") - (const_string "1")))]) - (define_insn "extendqisi2" [(set (match_operand:SI 0 "register_operand" "=r") (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")))] @@ -4090,6 +3968,32 @@ "movs{bl|x}\t{%1, %k0|%k0, %1}" [(set_attr "type" "imovx") (set_attr "mode" "SI")]) + +(define_insn "extendqihi2" + [(set (match_operand:HI 0 "register_operand" "=*a,r") + (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "*0,qm")))] + "" +{ + switch (get_attr_prefix_0f (insn)) + { + case 0: + return "{cbtw|cbw}"; + default: + return "movs{bw|x}\t{%1, %0|%0, %1}"; + } +} + [(set_attr "type" "imovx") + (set_attr "mode" "HI") + (set (attr "prefix_0f") + ;; movsx is short decodable while cwtl is vector decoded. + (if_then_else (and (eq_attr "cpu" "!k6") + (eq_attr "alternative" "0")) + (const_string "0") + (const_string "1"))) + (set (attr "modrm") + (if_then_else (eq_attr "prefix_0f" "0") + (const_string "0") + (const_string "1")))]) ;; Conversions between float and double.