From: Uros Bizjak Date: Fri, 9 Apr 2010 13:29:24 +0000 (+0200) Subject: i386.md (DWI): New mode iterator. X-Git-Tag: releases/gcc-4.6.0~7984 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=014753cc4d898e889ab04dcdb41bb6cc99645e69;p=thirdparty%2Fgcc.git i386.md (DWI): New mode iterator. * config/i386/i386.md (DWI): New mode iterator. (S): New mode attribute. (shift_operand): Ditto. (shift_immediate_operand): Ditto. (ashl_input_operand): Ditto. (ashl3): Macroize expander from ashl{qi,hi,si,di,ti}3_1 using SDWIM mode iterator. (*ashl3_doubleword): New insn_and_split_pattern. Macroize pattern from *ashl{di,ti}3_1 and corresponding splitters using DWI mode iterator. (*ashl3_doubleword peephole2): Macroize peephole2 pattern from corresponding peephole2 patterns. (x86_shift_adj_1): Macroize expander from x86_shift_adj_1 and x86_64_shift_adj_1 using SWI48 mode iterator. (x86_shift_adj_2): Ditto. (*ashldi3_1_rex64): Split TYPE_LEA pattern. (*ashl3_1): Macroize insn from *ashlsi3_1 and *ashldi3_1_rex64 using SWI48 mode iterator. (*ashl3_cmp): Macroize insn from *ashl{qi,hi,si}3_cmp and *ashldi3_cmp_rex64 using SWI mode iterator. (*ashl3_cconly): Macroize insn from *ashl{qi,hi,si}3_cconly and *ashldi3_cconly_rex64 using SWI mode iterator. * config/i386/i386.c (ix86_split_ashl): Update for renamed x86_shift_adj_{1,2}. (ix86_split_ashr): Ditto. (ix86_split_lshr): Ditto. From-SVN: r158163 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ce2a4955295a..0a11d90303b5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,32 @@ +2010-04-09 Uros Bizjak + + * config/i386/i386.md (DWI): New mode iterator. + (S): New mode attribute. + (shift_operand): Ditto. + (shift_immediate_operand): Ditto. + (ashl_input_operand): Ditto. + (ashl3): Macroize expander from ashl{qi,hi,si,di,ti}3_1 + using SDWIM mode iterator. + (*ashl3_doubleword): New insn_and_split_pattern. Macroize + pattern from *ashl{di,ti}3_1 and corresponding splitters using + DWI mode iterator. + (*ashl3_doubleword peephole2): Macroize peephole2 pattern + from corresponding peephole2 patterns. + (x86_shift_adj_1): Macroize expander from x86_shift_adj_1 + and x86_64_shift_adj_1 using SWI48 mode iterator. + (x86_shift_adj_2): Ditto. + (*ashldi3_1_rex64): Split TYPE_LEA pattern. + (*ashl3_1): Macroize insn from *ashlsi3_1 and *ashldi3_1_rex64 + using SWI48 mode iterator. + (*ashl3_cmp): Macroize insn from *ashl{qi,hi,si}3_cmp and + *ashldi3_cmp_rex64 using SWI mode iterator. + (*ashl3_cconly): Macroize insn from *ashl{qi,hi,si}3_cconly and + *ashldi3_cconly_rex64 using SWI mode iterator. + * config/i386/i386.c (ix86_split_ashl): Update for renamed + x86_shift_adj_{1,2}. + (ix86_split_ashr): Ditto. + (ix86_split_lshr): Ditto. + 2010-04-09 Richard Guenther * target.h (builtin_conversion): Pass in input and output types. @@ -58,8 +87,7 @@ (x86_this_parameter): Likewise. (x86_output_mi_thunk): Likewise. (ix86_attribute_table): Add description for thiscall attribute. - * config/i386/i386.h (ix86_args): Adjust comment for member - fastcall. + * config/i386/i386.h (ix86_args): Adjust comment for member fastcall. * doc/extend.texi: Add documentation for thiscall. 2010-04-09 Manuel López-Ibáñez @@ -83,8 +111,8 @@ PR tree-optimization/42720 * tree-ssa-loop-unswitch.c (tree_ssa_unswitch_loops): Move one-time - loop unswitch conditions here from - (tree_unswitch_single_loop). + loop unswitch conditions here from ... + (tree_unswitch_single_loop): ... here. 2010-04-08 Sebastian Pop @@ -108,14 +136,15 @@ 2010-04-08 Christian Borntraeger Wolfgang Gellerich - Implement target hook for loop unrolling - * target.h (loop_unroll_adjust): Add a new target hook function. - * target-def.h (TARGET_LOOP_UNROLL_ADJUST): Likewise. - * doc/tm.texi (TARGET_LOOP_UNROLL_ADJUST): Document it. - * config/s390/s390.c (TARGET_LOOP_UNROLL_ADJUST): Define it. - (s390_loop_unroll_adjust): Implement the new target hook for s390. - * loop-unroll.c (decide_unroll_runtime_iterations): Call loop unroll target hook - (decide_unroll_stupid): Likewise. + Implement target hook for loop unrolling + * target.h (loop_unroll_adjust): Add a new target hook function. + * target-def.h (TARGET_LOOP_UNROLL_ADJUST): Likewise. + * doc/tm.texi (TARGET_LOOP_UNROLL_ADJUST): Document it. + * config/s390/s390.c (TARGET_LOOP_UNROLL_ADJUST): Define it. + (s390_loop_unroll_adjust): Implement the new target hook for s390. + * loop-unroll.c (decide_unroll_runtime_iterations): Call loop unroll + target hook. + (decide_unroll_stupid): Likewise. 2010-04-08 Rainer Orth @@ -131,8 +160,8 @@ 2010-04-08 Wolfgang Gellerich * config/s390/s390.c (override_options): Adjust the z10 - defaults for max-unroll-times, max-completely-peeled-insns - and max-completely-peel-times. + defaults for max-unroll-times, max-completely-peeled-insns + and max-completely-peel-times. 2010-04-08 Andreas Krebbel @@ -283,8 +312,7 @@ * tree-ssa-forwprop.c (forward_propagate_into_gimple_cond): Handle reversed comparison ops. * tree-sra.c (asm_visit_addr): Use get_base_address. - * ipa-prop.c (visit_store_addr_for_mod_analysis): Use - get_base_address. + * ipa-prop.c (visit_store_addr_for_mod_analysis): Use get_base_address. * ipa-reference.c (mark_address): Use get_base_address. 2010-04-07 Richard Guenther @@ -305,10 +333,8 @@ * doc/invoke.texi (-fargument-alias, -fargument-noalias, -fargument-noalias-global, -fargument-noalias-anything): Remove. * common.opt: Likewise. - * tree-ssa-structalias.c (intra_create_variable_infos): Adjust - comment. - * alias.c (base_alias_check): Remove flag_argument_noalias - handling. + * tree-ssa-structalias.c (intra_create_variable_infos): Adjust comment. + * alias.c (base_alias_check): Remove flag_argument_noalias handling. (nonoverlapping_memrefs_p): Likewise. * emit-rtl.c (set_mem_attributes_minus_bitpos): Likewise. * opts.c (common_handle_option): Handle OPT_fargument_alias, @@ -318,8 +344,7 @@ 2010-04-07 Richard Guenther PR tree-optimization/43270 - * tree-vrp.c (check_array_ref): Fix flexible array member - detection. + * tree-vrp.c (check_array_ref): Fix flexible array member detection. * tree-ssa-sccvn.h (fully_constant_vn_reference_p): Declare. * tree-ssa-pre.c (phi_translate_1): Adjust. (fully_constant_expression): Split out vn_reference handling to ... @@ -340,15 +365,13 @@ 2010-04-07 Rainer Orth - * config.gcc (i[34567]86-*-solaris2*): Default with_tune_32 to - generic. + * config.gcc (i[34567]86-*-solaris2*): Default with_tune_32 to generic. 2010-04-07 Richard Guenther PR middle-end/42617 - * expr.c (expand_expr_real_1): For TARGET_MEM_REFs with - pointer bases build simple mem attributes to retain - points-to information. + * expr.c (expand_expr_real_1): For TARGET_MEM_REFs with pointer + bases build simple mem attributes to retain points-to information. 2010-04-07 Richard Guenther @@ -361,8 +384,7 @@ PR middle-end/42617 * emit-rtl.c (set_mem_attributes_minus_bitpos): Do not discard plain indirect references. - * fold-const.c (operand_equal_p): Guard against NULL_TREE - type. + * fold-const.c (operand_equal_p): Guard against NULL_TREE type. * tree.c (tree_nop_conversion): Likewise. 2010-04-07 Dodji Seketeli @@ -391,11 +413,13 @@ PR middle-end/43519 * graphite-clast-to-gimple.c (max_signed_precision_type): Use - lang_hooks.types.type_for_size instead of build_nonstandard_integer_type. + lang_hooks.types.type_for_size instead of + build_nonstandard_integer_type. When converting an unsigned type to signed, double its precision. (gcc_type_for_interval): Use lang_hooks.types.type_for_size. (gcc_type_for_iv_of_clast_loop): Call max_signed_precision_type. - (graphite_create_new_loop_guard): When ub + 1 wraps around, use lb <= ub. + (graphite_create_new_loop_guard): When ub + 1 wraps around, + use lb <= ub. 2010-04-06 Sebastian Pop @@ -631,8 +655,7 @@ 2010-04-02 Joseph Myers - * read-rtl.c (read_rtx_1): Give an error for EOF while looking for - ']'. + * read-rtl.c (read_rtx_1): Give an error for EOF while looking for ']'. 2010-04-02 Richard Earnshaw @@ -656,12 +679,12 @@ 2010-04-01 Ralf Corsépius - * config.gcc (lm32-*-rtems*): Add t-lm32. + * config.gcc (lm32-*-rtems*): Add t-lm32. 2010-04-01 Joel Sherrill - * config.gcc: Add lm32-*-rtems*. - * config/lm32/rtems.h: New file. + * config.gcc: Add lm32-*-rtems*. + * config/lm32/rtems.h: New file. 2010-04-01 Dave Korn @@ -714,7 +737,7 @@ PR middle-end/43602 Revert 2010-03-30 Seongbae Park - Jack Howarth + Jack Howarth * tree-profile.c (tree_init_ic_make_global_vars): Make static variables TLS. @@ -746,8 +769,7 @@ Update IDO URL. Document GNU as requirement. Update configure requirements. - (Specific, mips-sgi-irix6): Document IRIX 6 < 6.5 obsoletion, - removal. + (Specific, mips-sgi-irix6): Document IRIX 6 < 6.5 obsoletion, removal. Recomment IRIX 6.5.18+. Document IDF/IDL requirement. Document GNU as requirement. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 407e37c7067f..6431d9bfa322 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -17130,20 +17130,22 @@ ix86_split_ashl (rtx *operands, rtx scratch, enum machine_mode mode) : gen_x86_64_shld) (high[0], low[0], operands[2])); } - emit_insn ((mode == DImode ? gen_ashlsi3 : gen_ashldi3) (low[0], low[0], operands[2])); + emit_insn ((mode == DImode + ? gen_ashlsi3 + : gen_ashldi3) (low[0], low[0], operands[2])); if (TARGET_CMOVE && scratch) { ix86_expand_clear (scratch); emit_insn ((mode == DImode - ? gen_x86_shift_adj_1 - : gen_x86_64_shift_adj_1) (high[0], low[0], operands[2], - scratch)); + ? gen_x86_shiftsi_adj_1 + : gen_x86_shiftdi_adj_1) (high[0], low[0], operands[2], + scratch)); } else emit_insn ((mode == DImode - ? gen_x86_shift_adj_2 - : gen_x86_64_shift_adj_2) (high[0], low[0], operands[2])); + ? gen_x86_shiftsi_adj_2 + : gen_x86_shiftdi_adj_2) (high[0], low[0], operands[2])); } void @@ -17216,9 +17218,9 @@ ix86_split_ashr (rtx *operands, rtx scratch, enum machine_mode mode) : gen_ashrdi3) (scratch, scratch, GEN_INT (single_width - 1))); emit_insn ((mode == DImode - ? gen_x86_shift_adj_1 - : gen_x86_64_shift_adj_1) (low[0], high[0], operands[2], - scratch)); + ? gen_x86_shiftsi_adj_1 + : gen_x86_shiftdi_adj_1) (low[0], high[0], operands[2], + scratch)); } else emit_insn ((mode == DImode @@ -17281,14 +17283,14 @@ ix86_split_lshr (rtx *operands, rtx scratch, enum machine_mode mode) { ix86_expand_clear (scratch); emit_insn ((mode == DImode - ? gen_x86_shift_adj_1 - : gen_x86_64_shift_adj_1) (low[0], high[0], operands[2], - scratch)); + ? gen_x86_shiftsi_adj_1 + : gen_x86_shiftdi_adj_1) (low[0], high[0], operands[2], + scratch)); } else emit_insn ((mode == DImode - ? gen_x86_shift_adj_2 - : gen_x86_64_shift_adj_2) (low[0], high[0], operands[2])); + ? gen_x86_shiftsi_adj_2 + : gen_x86_shiftdi_adj_2) (low[0], high[0], operands[2])); } } diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 8bd8e0f133ab..b53c01daddb4 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -771,14 +771,18 @@ (define_mode_iterator SWIM248 [(HI "TARGET_HIMODE_MATH") SI (DI "TARGET_64BIT")]) -;; Half mode for double word integer modes. -(define_mode_iterator DWIH [(SI "!TARGET_64BIT") - (DI "TARGET_64BIT")]) - ;; Double word integer modes. +(define_mode_iterator DWI [(DI "!TARGET_64BIT") + (TI "TARGET_64BIT")]) + +;; Double word integer modes as mode attribute. (define_mode_attr DWI [(SI "DI") (DI "TI")]) (define_mode_attr dwi [(SI "di") (DI "ti")]) +;; Half mode for double word integer modes. +(define_mode_iterator DWIH [(SI "!TARGET_64BIT") + (DI "TARGET_64BIT")]) + ;; Instruction suffix for integer modes. (define_mode_attr imodesuffix [(QI "b") (HI "w") (SI "l") (DI "q")]) @@ -794,6 +798,9 @@ ;; Immediate operand constraint for double integer modes. (define_mode_attr di [(SI "iF") (DI "e")]) +;; Immediate operand constraint for shifts. +(define_mode_attr S [(QI "I") (HI "I") (SI "I") (DI "J") (TI "O")]) + ;; General operand predicate for integer modes. (define_mode_attr general_operand [(QI "general_operand") @@ -809,6 +816,29 @@ (SI "general_operand") (DI "x86_64_szext_general_operand")]) +;; Operand predicate for shifts. +(define_mode_attr shift_operand + [(QI "nonimmediate_operand") + (HI "nonimmediate_operand") + (SI "nonimmediate_operand") + (DI "shiftdi_operand") + (TI "register_operand")]) + +;; Operand predicate for shift argument. +(define_mode_attr shift_immediate_operand + [(QI "const_1_to_31_operand") + (HI "const_1_to_31_operand") + (SI "const_1_to_31_operand") + (DI "const_1_to_63_operand")]) + +;; Input operand predicate for arithmetic left shifts. +(define_mode_attr ashl_input_operand + [(QI "nonimmediate_operand") + (HI "nonimmediate_operand") + (SI "nonimmediate_operand") + (DI "ashldi_input_operand") + (TI "reg_or_pm1_operand")]) + ;; SSE and x87 SFmode and DFmode floating point modes (define_mode_iterator MODEF [SF DF]) @@ -9523,42 +9553,40 @@ ;; shift pair, instead using moves and sign extension for counts greater ;; than 31. -(define_expand "ashlti3" - [(set (match_operand:TI 0 "register_operand" "") - (ashift:TI (match_operand:TI 1 "reg_or_pm1_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "TARGET_64BIT" - "ix86_expand_binary_operator (ASHIFT, TImode, operands); DONE;") +(define_expand "ashl3" + [(set (match_operand:SDWIM 0 "" "") + (ashift:SDWIM (match_operand:SDWIM 1 "" "") + (match_operand:QI 2 "nonmemory_operand" "")))] + "" + "ix86_expand_binary_operator (ASHIFT, mode, operands); DONE;") -(define_insn "*ashlti3_1" - [(set (match_operand:TI 0 "register_operand" "=&r,r") - (ashift:TI (match_operand:TI 1 "reg_or_pm1_operand" "n,0") - (match_operand:QI 2 "nonmemory_operand" "Oc,Oc"))) +(define_insn_and_split "*ashl3_doubleword" + [(set (match_operand:DWI 0 "register_operand" "=&r,r") + (ashift:DWI (match_operand:DWI 1 "reg_or_pm1_operand" "n,0") + (match_operand:QI 2 "nonmemory_operand" "c,c"))) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT" + "ix86_binary_operator_ok (ASHIFT, mode, operands)" "#" + "(optimize && flag_peephole2) ? epilogue_completed : reload_completed" + [(const_int 0)] + "ix86_split_ashl (operands, NULL_RTX, mode); DONE;" [(set_attr "type" "multi")]) +;; By default we don't ask for a scratch register, because when DWImode +;; values are manipulated, registers are already at a premium. But if +;; we have one handy, we won't turn it away. + (define_peephole2 - [(match_scratch:DI 3 "r") - (parallel [(set (match_operand:TI 0 "register_operand" "") - (ashift:TI (match_operand:TI 1 "nonmemory_operand" "") - (match_operand:QI 2 "nonmemory_operand" ""))) + [(match_scratch:DWIH 3 "r") + (parallel [(set (match_operand: 0 "register_operand" "") + (ashift: + (match_operand: 1 "nonmemory_operand" "") + (match_operand:QI 2 "nonmemory_operand" ""))) (clobber (reg:CC FLAGS_REG))]) (match_dup 3)] - "TARGET_64BIT" - [(const_int 0)] - "ix86_split_ashl (operands, operands[3], TImode); DONE;") - -(define_split - [(set (match_operand:TI 0 "register_operand" "") - (ashift:TI (match_operand:TI 1 "nonmemory_operand" "") - (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ((optimize > 0 && flag_peephole2) - ? epilogue_completed : reload_completed)" + "TARGET_CMOVE" [(const_int 0)] - "ix86_split_ashl (operands, NULL_RTX, TImode); DONE;") + "ix86_split_ashl (operands, operands[3], mode); DONE;") (define_insn "x86_64_shld" [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m") @@ -9575,32 +9603,49 @@ (set_attr "athlon_decode" "vector") (set_attr "amdfam10_decode" "vector")]) -(define_expand "x86_64_shift_adj_1" +(define_insn "x86_shld" + [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m") + (ior:SI (ashift:SI (match_dup 0) + (match_operand:QI 2 "nonmemory_operand" "Ic")) + (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") + (minus:QI (const_int 32) (match_dup 2))))) + (clobber (reg:CC FLAGS_REG))] + "" + "shld{l}\t{%s2%1, %0|%0, %1, %2}" + [(set_attr "type" "ishift") + (set_attr "prefix_0f" "1") + (set_attr "mode" "SI") + (set_attr "pent_pair" "np") + (set_attr "athlon_decode" "vector") + (set_attr "amdfam10_decode" "vector")]) + +(define_expand "x86_shift_adj_1" [(set (reg:CCZ FLAGS_REG) (compare:CCZ (and:QI (match_operand:QI 2 "register_operand" "") - (const_int 64)) + (match_dup 4)) (const_int 0))) - (set (match_operand:DI 0 "register_operand" "") - (if_then_else:DI (ne (reg:CCZ FLAGS_REG) (const_int 0)) - (match_operand:DI 1 "register_operand" "") - (match_dup 0))) + (set (match_operand:SWI48 0 "register_operand" "") + (if_then_else:SWI48 (ne (reg:CCZ FLAGS_REG) (const_int 0)) + (match_operand:SWI48 1 "register_operand" "") + (match_dup 0))) (set (match_dup 1) - (if_then_else:DI (ne (reg:CCZ FLAGS_REG) (const_int 0)) - (match_operand:DI 3 "register_operand" "r") - (match_dup 1)))] - "TARGET_64BIT" - "") + (if_then_else:SWI48 (ne (reg:CCZ FLAGS_REG) (const_int 0)) + (match_operand:SWI48 3 "register_operand" "r") + (match_dup 1)))] + "TARGET_CMOVE" + "operands[4] = GEN_INT (GET_MODE_BITSIZE (mode));") -(define_expand "x86_64_shift_adj_2" - [(use (match_operand:DI 0 "register_operand" "")) - (use (match_operand:DI 1 "register_operand" "")) +(define_expand "x86_shift_adj_2" + [(use (match_operand:SWI48 0 "register_operand" "")) + (use (match_operand:SWI48 1 "register_operand" "")) (use (match_operand:QI 2 "register_operand" ""))] - "TARGET_64BIT" + "" { rtx label = gen_label_rtx (); rtx tmp; - emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (64))); + emit_insn (gen_testqi_ccz_1 (operands[2], + GEN_INT (GET_MODE_BITSIZE (mode)))); tmp = gen_rtx_REG (CCZmode, FLAGS_REG); tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); @@ -9619,42 +9664,31 @@ DONE; }) -(define_expand "ashldi3" - [(set (match_operand:DI 0 "shiftdi_operand" "") - (ashift:DI (match_operand:DI 1 "ashldi_input_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - "ix86_expand_binary_operator (ASHIFT, DImode, operands); DONE;") - -(define_insn "*ashldi3_1_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r") - (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0,l") - (match_operand:QI 2 "nonmemory_operand" "cJ,M"))) +(define_insn "*ashl3_1" + [(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r") + (ashift:SWI48 (match_operand:SWI48 1 "nonimmediate_operand" "0,l") + (match_operand:QI 2 "nonmemory_operand" "c,M"))) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (ASHIFT, DImode, operands)" + "ix86_binary_operator_ok (ASHIFT, mode, operands)" { switch (get_attr_type (insn)) { case TYPE_ALU: gcc_assert (operands[2] == const1_rtx); gcc_assert (rtx_equal_p (operands[0], operands[1])); - return "add{q}\t%0, %0"; + return "add{}\t%0, %0"; case TYPE_LEA: - gcc_assert (CONST_INT_P (operands[2])); - gcc_assert ((unsigned HOST_WIDE_INT) INTVAL (operands[2]) <= 3); - operands[1] = gen_rtx_MULT (DImode, operands[1], - GEN_INT (1 << INTVAL (operands[2]))); - return "lea{q}\t{%a1, %0|%0, %a1}"; + return "#"; default: if (REG_P (operands[2])) - return "sal{q}\t{%b2, %0|%0, %b2}"; + return "sal{}\t{%b2, %0|%0, %b2}"; else if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{q}\t%0"; + return "sal{}\t%0"; else - return "sal{q}\t{%2, %0|%0, %2}"; + return "sal{}\t{%2, %0|%0, %2}"; } } [(set (attr "type") @@ -9676,61 +9710,40 @@ (const_int 0))))) (const_string "0") (const_string "*"))) - (set_attr "mode" "DI")]) + (set_attr "mode" "")]) -;; Convert lea to the lea pattern to avoid flags dependency. -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (ashift:DI (match_operand:DI 1 "index_register_operand" "") - (match_operand:QI 2 "immediate_operand" ""))) +(define_insn "*ashlsi3_1_zext" + [(set (match_operand:DI 0 "register_operand" "=r,r") + (zero_extend:DI + (ashift:SI (match_operand:SI 1 "register_operand" "0,l") + (match_operand:QI 2 "nonmemory_operand" "cI,M")))) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && reload_completed - && true_regnum (operands[0]) != true_regnum (operands[1])" - [(set (match_dup 0) - (mult:DI (match_dup 1) - (match_dup 2)))] - "operands[2] = gen_int_mode (1 << INTVAL (operands[2]), DImode);") - -;; This pattern can't accept a variable shift count, since shifts by -;; zero don't affect the flags. We assume that shifts by constant -;; zero are optimized away. -(define_insn "*ashldi3_cmp_rex64" - [(set (reg FLAGS_REG) - (compare - (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_63_operand" "J")) - (const_int 0))) - (set (match_operand:DI 0 "nonimmediate_operand" "=rm") - (ashift:DI (match_dup 1) (match_dup 2)))] - "TARGET_64BIT - && (optimize_function_for_size_p (cfun) - || !TARGET_PARTIAL_FLAG_REG_STALL - || (operands[2] == const1_rtx - && (TARGET_SHIFT1 - || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0]))))) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFT, DImode, operands)" + "TARGET_64BIT && ix86_binary_operator_ok (ASHIFT, SImode, operands)" { switch (get_attr_type (insn)) { case TYPE_ALU: gcc_assert (operands[2] == const1_rtx); - return "add{q}\t%0, %0"; + return "add{l}\t%k0, %k0"; + + case TYPE_LEA: + return "#"; default: if (REG_P (operands[2])) - return "sal{q}\t{%b2, %0|%0, %b2}"; + return "sal{l}\t{%b2, %k0|%k0, %b2}"; else if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{q}\t%0"; + return "sal{l}\t%k0"; else - return "sal{q}\t{%2, %0|%0, %2}"; + return "sal{l}\t{%2, %k0|%k0, %2}"; } } [(set (attr "type") - (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") - (const_int 0)) - (match_operand 0 "register_operand" "")) + (cond [(eq_attr "alternative" "1") + (const_string "lea") + (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") + (const_int 0)) (match_operand 2 "const1_operand" "")) (const_string "alu") ] @@ -9744,38 +9757,30 @@ (const_int 0))))) (const_string "0") (const_string "*"))) - (set_attr "mode" "DI")]) + (set_attr "mode" "SI")]) -(define_insn "*ashldi3_cconly_rex64" - [(set (reg FLAGS_REG) - (compare - (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_63_operand" "J")) - (const_int 0))) - (clobber (match_scratch:DI 0 "=r"))] - "TARGET_64BIT - && (optimize_function_for_size_p (cfun) - || !TARGET_PARTIAL_FLAG_REG_STALL - || (operands[2] == const1_rtx - && (TARGET_SHIFT1 - || TARGET_DOUBLE_WITH_ADD))) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFT, DImode, operands)" +(define_insn "*ashlhi3_1" + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") + (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "nonmemory_operand" "cI"))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_PARTIAL_REG_STALL + && ix86_binary_operator_ok (ASHIFT, HImode, operands)" { switch (get_attr_type (insn)) { case TYPE_ALU: gcc_assert (operands[2] == const1_rtx); - return "add{q}\t%0, %0"; + return "add{w}\t%0, %0"; default: if (REG_P (operands[2])) - return "sal{q}\t{%b2, %0|%0, %b2}"; + return "sal{w}\t{%b2, %0|%0, %b2}"; else if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{q}\t%0"; + return "sal{w}\t%0"; else - return "sal{q}\t{%2, %0|%0, %2}"; + return "sal{w}\t{%2, %0|%0, %2}"; } } [(set (attr "type") @@ -9795,133 +9800,32 @@ (const_int 0))))) (const_string "0") (const_string "*"))) - (set_attr "mode" "DI")]) - -(define_insn "*ashldi3_1" - [(set (match_operand:DI 0 "register_operand" "=&r,r") - (ashift:DI (match_operand:DI 1 "reg_or_pm1_operand" "n,0") - (match_operand:QI 2 "nonmemory_operand" "Jc,Jc"))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT" - "#" - [(set_attr "type" "multi")]) - -;; By default we don't ask for a scratch register, because when DImode -;; values are manipulated, registers are already at a premium. But if -;; we have one handy, we won't turn it away. -(define_peephole2 - [(match_scratch:SI 3 "r") - (parallel [(set (match_operand:DI 0 "register_operand" "") - (ashift:DI (match_operand:DI 1 "nonmemory_operand" "") - (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC FLAGS_REG))]) - (match_dup 3)] - "!TARGET_64BIT && TARGET_CMOVE" - [(const_int 0)] - "ix86_split_ashl (operands, operands[3], DImode); DONE;") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (ashift:DI (match_operand:DI 1 "nonmemory_operand" "") - (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT && ((optimize > 0 && flag_peephole2) - ? epilogue_completed : reload_completed)" - [(const_int 0)] - "ix86_split_ashl (operands, NULL_RTX, DImode); DONE;") - -(define_insn "x86_shld" - [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m") - (ior:SI (ashift:SI (match_dup 0) - (match_operand:QI 2 "nonmemory_operand" "Ic")) - (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") - (minus:QI (const_int 32) (match_dup 2))))) - (clobber (reg:CC FLAGS_REG))] - "" - "shld{l}\t{%s2%1, %0|%0, %1, %2}" - [(set_attr "type" "ishift") - (set_attr "prefix_0f" "1") - (set_attr "mode" "SI") - (set_attr "pent_pair" "np") - (set_attr "athlon_decode" "vector") - (set_attr "amdfam10_decode" "vector")]) - -(define_expand "x86_shift_adj_1" - [(set (reg:CCZ FLAGS_REG) - (compare:CCZ (and:QI (match_operand:QI 2 "register_operand" "") - (const_int 32)) - (const_int 0))) - (set (match_operand:SI 0 "register_operand" "") - (if_then_else:SI (ne (reg:CCZ FLAGS_REG) (const_int 0)) - (match_operand:SI 1 "register_operand" "") - (match_dup 0))) - (set (match_dup 1) - (if_then_else:SI (ne (reg:CCZ FLAGS_REG) (const_int 0)) - (match_operand:SI 3 "register_operand" "r") - (match_dup 1)))] - "TARGET_CMOVE" - "") - -(define_expand "x86_shift_adj_2" - [(use (match_operand:SI 0 "register_operand" "")) - (use (match_operand:SI 1 "register_operand" "")) - (use (match_operand:QI 2 "register_operand" ""))] - "" -{ - rtx label = gen_label_rtx (); - rtx tmp; - - emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (32))); - - tmp = gen_rtx_REG (CCZmode, FLAGS_REG); - tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, - gen_rtx_LABEL_REF (VOIDmode, label), - pc_rtx); - tmp = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp)); - JUMP_LABEL (tmp) = label; - - emit_move_insn (operands[0], operands[1]); - ix86_expand_clear (operands[1]); - - emit_label (label); - LABEL_NUSES (label) = 1; - - DONE; -}) - -(define_expand "ashlsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - "ix86_expand_binary_operator (ASHIFT, SImode, operands); DONE;") + (set_attr "mode" "HI")]) -(define_insn "*ashlsi3_1" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") - (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,l") +(define_insn "*ashlhi3_1_lea" + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") + (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0,l") (match_operand:QI 2 "nonmemory_operand" "cI,M"))) (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (ASHIFT, SImode, operands)" + "!TARGET_PARTIAL_REG_STALL + && ix86_binary_operator_ok (ASHIFT, HImode, operands)" { switch (get_attr_type (insn)) { - case TYPE_ALU: - gcc_assert (operands[2] == const1_rtx); - gcc_assert (rtx_equal_p (operands[0], operands[1])); - return "add{l}\t%0, %0"; - case TYPE_LEA: return "#"; + case TYPE_ALU: + gcc_assert (operands[2] == const1_rtx); + return "add{w}\t%0, %0"; default: if (REG_P (operands[2])) - return "sal{l}\t{%b2, %0|%0, %b2}"; + return "sal{w}\t{%b2, %0|%0, %b2}"; else if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{l}\t%0"; + return "sal{w}\t%0"; else - return "sal{l}\t{%2, %0|%0, %2}"; + return "sal{w}\t{%2, %0|%0, %2}"; } } [(set (attr "type") @@ -9943,452 +9847,48 @@ (const_int 0))))) (const_string "0") (const_string "*"))) - (set_attr "mode" "SI")]) + (set_attr "mode" "HI,SI")]) -;; Convert lea to the lea pattern to avoid flags dependency. -(define_split - [(set (match_operand 0 "register_operand" "") - (ashift (match_operand 1 "index_register_operand" "") - (match_operand:QI 2 "const_int_operand" ""))) +(define_insn "*ashlqi3_1" + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r") + (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") + (match_operand:QI 2 "nonmemory_operand" "cI,cI"))) (clobber (reg:CC FLAGS_REG))] - "reload_completed - && true_regnum (operands[0]) != true_regnum (operands[1]) - && GET_MODE_SIZE (GET_MODE (operands[0])) <= 4" - [(const_int 0)] + "TARGET_PARTIAL_REG_STALL + && ix86_binary_operator_ok (ASHIFT, QImode, operands)" { - rtx pat; - enum machine_mode mode = GET_MODE (operands[0]); - - if (GET_MODE_SIZE (mode) < 4) - operands[0] = gen_lowpart (SImode, operands[0]); - if (mode != Pmode) - operands[1] = gen_lowpart (Pmode, operands[1]); - operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode); - - pat = gen_rtx_MULT (Pmode, operands[1], operands[2]); - if (Pmode != SImode) - pat = gen_rtx_SUBREG (SImode, pat, 0); - emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat)); - DONE; -}) - -;; Rare case of shifting RSP is handled by generating move and shift -(define_split - [(set (match_operand 0 "register_operand" "") - (ashift (match_operand 1 "register_operand" "") - (match_operand:QI 2 "const_int_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "reload_completed - && true_regnum (operands[0]) != true_regnum (operands[1])" - [(const_int 0)] -{ - rtx pat, clob; - emit_move_insn (operands[0], operands[1]); - pat = gen_rtx_SET (VOIDmode, operands[0], - gen_rtx_ASHIFT (GET_MODE (operands[0]), - operands[0], operands[2])); - clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG)); - emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, pat, clob))); - DONE; -}) - -(define_insn "*ashlsi3_1_zext" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (zero_extend:DI (ashift:SI (match_operand:SI 1 "register_operand" "0,l") - (match_operand:QI 2 "nonmemory_operand" "cI,M")))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (ASHIFT, SImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_ALU: - gcc_assert (operands[2] == const1_rtx); - return "add{l}\t%k0, %k0"; - - case TYPE_LEA: - return "#"; - - default: - if (REG_P (operands[2])) - return "sal{l}\t{%b2, %k0|%k0, %b2}"; - else if (operands[2] == const1_rtx - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{l}\t%k0"; - else - return "sal{l}\t{%2, %k0|%k0, %2}"; - } -} - [(set (attr "type") - (cond [(eq_attr "alternative" "1") - (const_string "lea") - (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") - (const_int 0)) - (match_operand 2 "const1_operand" "")) - (const_string "alu") - ] - (const_string "ishift"))) - (set (attr "length_immediate") - (if_then_else - (ior (eq_attr "type" "alu") - (and (eq_attr "type" "ishift") - (and (match_operand 2 "const1_operand" "") - (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") - (const_int 0))))) - (const_string "0") - (const_string "*"))) - (set_attr "mode" "SI")]) - -;; Convert lea to the lea pattern to avoid flags dependency. -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (zero_extend:DI (ashift (match_operand 1 "register_operand" "") - (match_operand:QI 2 "const_int_operand" "")))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && reload_completed - && true_regnum (operands[0]) != true_regnum (operands[1])" - [(set (match_dup 0) (zero_extend:DI - (subreg:SI (mult:SI (match_dup 1) - (match_dup 2)) 0)))] -{ - operands[1] = gen_lowpart (Pmode, operands[1]); - operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode); -}) - -;; This pattern can't accept a variable shift count, since shifts by -;; zero don't affect the flags. We assume that shifts by constant -;; zero are optimized away. -(define_insn "*ashlsi3_cmp" - [(set (reg FLAGS_REG) - (compare - (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I")) - (const_int 0))) - (set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (ashift:SI (match_dup 1) (match_dup 2)))] - "(optimize_function_for_size_p (cfun) - || !TARGET_PARTIAL_FLAG_REG_STALL - || (operands[2] == const1_rtx - && (TARGET_SHIFT1 - || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0]))))) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFT, SImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_ALU: - gcc_assert (operands[2] == const1_rtx); - return "add{l}\t%0, %0"; - - default: - if (REG_P (operands[2])) - return "sal{l}\t{%b2, %0|%0, %b2}"; - else if (operands[2] == const1_rtx - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{l}\t%0"; - else - return "sal{l}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") - (const_int 0)) - (match_operand 0 "register_operand" "")) - (match_operand 2 "const1_operand" "")) - (const_string "alu") - ] - (const_string "ishift"))) - (set (attr "length_immediate") - (if_then_else - (ior (eq_attr "type" "alu") - (and (eq_attr "type" "ishift") - (and (match_operand 2 "const1_operand" "") - (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") - (const_int 0))))) - (const_string "0") - (const_string "*"))) - (set_attr "mode" "SI")]) - -(define_insn "*ashlsi3_cconly" - [(set (reg FLAGS_REG) - (compare - (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I")) - (const_int 0))) - (clobber (match_scratch:SI 0 "=r"))] - "(optimize_function_for_size_p (cfun) - || !TARGET_PARTIAL_FLAG_REG_STALL - || (operands[2] == const1_rtx - && (TARGET_SHIFT1 - || TARGET_DOUBLE_WITH_ADD))) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFT, SImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_ALU: - gcc_assert (operands[2] == const1_rtx); - return "add{l}\t%0, %0"; - - default: - if (REG_P (operands[2])) - return "sal{l}\t{%b2, %0|%0, %b2}"; - else if (operands[2] == const1_rtx - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{l}\t%0"; - else - return "sal{l}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") - (const_int 0)) - (match_operand 0 "register_operand" "")) - (match_operand 2 "const1_operand" "")) - (const_string "alu") - ] - (const_string "ishift"))) - (set (attr "length_immediate") - (if_then_else - (ior (eq_attr "type" "alu") - (and (eq_attr "type" "ishift") - (and (match_operand 2 "const1_operand" "") - (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") - (const_int 0))))) - (const_string "0") - (const_string "*"))) - (set_attr "mode" "SI")]) - -(define_insn "*ashlsi3_cmp_zext" - [(set (reg FLAGS_REG) - (compare - (ashift:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I")) - (const_int 0))) - (set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI (ashift:SI (match_dup 1) (match_dup 2))))] - "TARGET_64BIT - && (optimize_function_for_size_p (cfun) - || !TARGET_PARTIAL_FLAG_REG_STALL - || (operands[2] == const1_rtx - && (TARGET_SHIFT1 - || TARGET_DOUBLE_WITH_ADD))) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFT, SImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_ALU: - gcc_assert (operands[2] == const1_rtx); - return "add{l}\t%k0, %k0"; - - default: - if (REG_P (operands[2])) - return "sal{l}\t{%b2, %k0|%k0, %b2}"; - else if (operands[2] == const1_rtx - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{l}\t%k0"; - else - return "sal{l}\t{%2, %k0|%k0, %2}"; - } -} - [(set (attr "type") - (cond [(and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") - (const_int 0)) - (match_operand 2 "const1_operand" "")) - (const_string "alu") - ] - (const_string "ishift"))) - (set (attr "length_immediate") - (if_then_else - (ior (eq_attr "type" "alu") - (and (eq_attr "type" "ishift") - (and (match_operand 2 "const1_operand" "") - (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") - (const_int 0))))) - (const_string "0") - (const_string "*"))) - (set_attr "mode" "SI")]) - -(define_expand "ashlhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "TARGET_HIMODE_MATH" - "ix86_expand_binary_operator (ASHIFT, HImode, operands); DONE;") - -(define_insn "*ashlhi3_1_lea" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") - (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0,l") - (match_operand:QI 2 "nonmemory_operand" "cI,M"))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_PARTIAL_REG_STALL - && ix86_binary_operator_ok (ASHIFT, HImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_LEA: - return "#"; - case TYPE_ALU: - gcc_assert (operands[2] == const1_rtx); - return "add{w}\t%0, %0"; - - default: - if (REG_P (operands[2])) - return "sal{w}\t{%b2, %0|%0, %b2}"; - else if (operands[2] == const1_rtx - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{w}\t%0"; - else - return "sal{w}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (cond [(eq_attr "alternative" "1") - (const_string "lea") - (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") - (const_int 0)) - (match_operand 0 "register_operand" "")) - (match_operand 2 "const1_operand" "")) - (const_string "alu") - ] - (const_string "ishift"))) - (set (attr "length_immediate") - (if_then_else - (ior (eq_attr "type" "alu") - (and (eq_attr "type" "ishift") - (and (match_operand 2 "const1_operand" "") - (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") - (const_int 0))))) - (const_string "0") - (const_string "*"))) - (set_attr "mode" "HI,SI")]) - -(define_insn "*ashlhi3_1" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "nonmemory_operand" "cI"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_PARTIAL_REG_STALL - && ix86_binary_operator_ok (ASHIFT, HImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_ALU: - gcc_assert (operands[2] == const1_rtx); - return "add{w}\t%0, %0"; - - default: - if (REG_P (operands[2])) - return "sal{w}\t{%b2, %0|%0, %b2}"; - else if (operands[2] == const1_rtx - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{w}\t%0"; - else - return "sal{w}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") - (const_int 0)) - (match_operand 0 "register_operand" "")) - (match_operand 2 "const1_operand" "")) - (const_string "alu") - ] - (const_string "ishift"))) - (set (attr "length_immediate") - (if_then_else - (ior (eq_attr "type" "alu") - (and (eq_attr "type" "ishift") - (and (match_operand 2 "const1_operand" "") - (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") - (const_int 0))))) - (const_string "0") - (const_string "*"))) - (set_attr "mode" "HI")]) - -;; This pattern can't accept a variable shift count, since shifts by -;; zero don't affect the flags. We assume that shifts by constant -;; zero are optimized away. -(define_insn "*ashlhi3_cmp" - [(set (reg FLAGS_REG) - (compare - (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I")) - (const_int 0))) - (set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (ashift:HI (match_dup 1) (match_dup 2)))] - "(optimize_function_for_size_p (cfun) - || !TARGET_PARTIAL_FLAG_REG_STALL - || (operands[2] == const1_rtx - && (TARGET_SHIFT1 - || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0]))))) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFT, HImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_ALU: - gcc_assert (operands[2] == const1_rtx); - return "add{w}\t%0, %0"; - - default: - if (REG_P (operands[2])) - return "sal{w}\t{%b2, %0|%0, %b2}"; - else if (operands[2] == const1_rtx - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{w}\t%0"; - else - return "sal{w}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") - (const_int 0)) - (match_operand 0 "register_operand" "")) - (match_operand 2 "const1_operand" "")) - (const_string "alu") - ] - (const_string "ishift"))) - (set (attr "length_immediate") - (if_then_else - (ior (eq_attr "type" "alu") - (and (eq_attr "type" "ishift") - (and (match_operand 2 "const1_operand" "") - (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)") - (const_int 0))))) - (const_string "0") - (const_string "*"))) - (set_attr "mode" "HI")]) - -(define_insn "*ashlhi3_cconly" - [(set (reg FLAGS_REG) - (compare - (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I")) - (const_int 0))) - (clobber (match_scratch:HI 0 "=r"))] - "(optimize_function_for_size_p (cfun) - || !TARGET_PARTIAL_FLAG_REG_STALL - || (operands[2] == const1_rtx - && (TARGET_SHIFT1 - || TARGET_DOUBLE_WITH_ADD))) - && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFT, HImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_ALU: - gcc_assert (operands[2] == const1_rtx); - return "add{w}\t%0, %0"; + switch (get_attr_type (insn)) + { + case TYPE_ALU: + gcc_assert (operands[2] == const1_rtx); + if (REG_P (operands[1]) && !ANY_QI_REG_P (operands[1])) + return "add{l}\t%k0, %k0"; + else + return "add{b}\t%0, %0"; default: if (REG_P (operands[2])) - return "sal{w}\t{%b2, %0|%0, %b2}"; + { + if (get_attr_mode (insn) == MODE_SI) + return "sal{l}\t{%b2, %k0|%k0, %b2}"; + else + return "sal{b}\t{%b2, %0|%0, %b2}"; + } else if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{w}\t%0"; + { + if (get_attr_mode (insn) == MODE_SI) + return "sal{l}\t%0"; + else + return "sal{b}\t%0"; + } else - return "sal{w}\t{%2, %0|%0, %2}"; + { + if (get_attr_mode (insn) == MODE_SI) + return "sal{l}\t{%2, %k0|%k0, %2}"; + else + return "sal{b}\t{%2, %0|%0, %2}"; + } } } [(set (attr "type") @@ -10408,17 +9908,9 @@ (const_int 0))))) (const_string "0") (const_string "*"))) - (set_attr "mode" "HI")]) - -(define_expand "ashlqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "TARGET_QIMODE_MATH" - "ix86_expand_binary_operator (ASHIFT, QImode, operands); DONE;") + (set_attr "mode" "QI,SI")]) ;; %%% Potential partial reg stall on alternative 2. What to do? - (define_insn "*ashlqi3_1_lea" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r,r") (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,l") @@ -10484,46 +9976,113 @@ (const_string "*"))) (set_attr "mode" "QI,SI,SI")]) -(define_insn "*ashlqi3_1" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r") - (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "cI,cI"))) +;; Convert lea to the lea pattern to avoid flags dependency. +(define_split + [(set (match_operand:DI 0 "register_operand" "") + (ashift:DI (match_operand:DI 1 "index_register_operand" "") + (match_operand:QI 2 "const_int_operand" ""))) (clobber (reg:CC FLAGS_REG))] - "TARGET_PARTIAL_REG_STALL - && ix86_binary_operator_ok (ASHIFT, QImode, operands)" + "TARGET_64BIT && reload_completed + && true_regnum (operands[0]) != true_regnum (operands[1])" + [(set (match_dup 0) + (mult:DI (match_dup 1) + (match_dup 2)))] + "operands[2] = gen_int_mode (1 << INTVAL (operands[2]), DImode);") + +;; Convert lea to the lea pattern to avoid flags dependency. +(define_split + [(set (match_operand 0 "register_operand" "") + (ashift (match_operand 1 "index_register_operand" "") + (match_operand:QI 2 "const_int_operand" ""))) + (clobber (reg:CC FLAGS_REG))] + "reload_completed + && true_regnum (operands[0]) != true_regnum (operands[1]) + && GET_MODE_SIZE (GET_MODE (operands[0])) <= 4" + [(const_int 0)] +{ + rtx pat; + enum machine_mode mode = GET_MODE (operands[0]); + + if (GET_MODE_SIZE (mode) < 4) + operands[0] = gen_lowpart (SImode, operands[0]); + if (mode != Pmode) + operands[1] = gen_lowpart (Pmode, operands[1]); + operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode); + + pat = gen_rtx_MULT (Pmode, operands[1], operands[2]); + if (Pmode != SImode) + pat = gen_rtx_SUBREG (SImode, pat, 0); + emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat)); + DONE; +}) + +;; Rare case of shifting RSP is handled by generating move and shift +(define_split + [(set (match_operand 0 "register_operand" "") + (ashift (match_operand 1 "register_operand" "") + (match_operand:QI 2 "const_int_operand" ""))) + (clobber (reg:CC FLAGS_REG))] + "reload_completed + && true_regnum (operands[0]) != true_regnum (operands[1])" + [(const_int 0)] +{ + rtx pat, clob; + emit_move_insn (operands[0], operands[1]); + pat = gen_rtx_SET (VOIDmode, operands[0], + gen_rtx_ASHIFT (GET_MODE (operands[0]), + operands[0], operands[2])); + clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG)); + emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, pat, clob))); + DONE; +}) + +;; Convert lea to the lea pattern to avoid flags dependency. +(define_split + [(set (match_operand:DI 0 "register_operand" "") + (zero_extend:DI + (ashift:SI (match_operand:SI 1 "register_operand" "") + (match_operand:QI 2 "const_int_operand" "")))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT && reload_completed + && true_regnum (operands[0]) != true_regnum (operands[1])" + [(set (match_dup 0) + (zero_extend:DI (subreg:SI (mult:SI (match_dup 1) (match_dup 2)) 0)))] +{ + operands[1] = gen_lowpart (Pmode, operands[1]); + operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode); +}) + +;; This pattern can't accept a variable shift count, since shifts by +;; zero don't affect the flags. We assume that shifts by constant +;; zero are optimized away. +(define_insn "*ashl3_cmp" + [(set (reg FLAGS_REG) + (compare + (ashift:SWI (match_operand:SWI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "" "")) + (const_int 0))) + (set (match_operand:SWI 0 "nonimmediate_operand" "=m") + (ashift:SWI (match_dup 1) (match_dup 2)))] + "(optimize_function_for_size_p (cfun) + || !TARGET_PARTIAL_FLAG_REG_STALL + || (operands[2] == const1_rtx + && (TARGET_SHIFT1 + || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0]))))) + && ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (ASHIFT, mode, operands)" { switch (get_attr_type (insn)) { case TYPE_ALU: gcc_assert (operands[2] == const1_rtx); - if (REG_P (operands[1]) && !ANY_QI_REG_P (operands[1])) - return "add{l}\t%k0, %k0"; - else - return "add{b}\t%0, %0"; + return "add{}\t%0, %0"; default: - if (REG_P (operands[2])) - { - if (get_attr_mode (insn) == MODE_SI) - return "sal{l}\t{%b2, %k0|%k0, %b2}"; - else - return "sal{b}\t{%b2, %0|%0, %b2}"; - } - else if (operands[2] == const1_rtx - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - { - if (get_attr_mode (insn) == MODE_SI) - return "sal{l}\t%0"; - else - return "sal{b}\t%0"; - } + if (operands[2] == const1_rtx + && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) + return "sal{}\t%0"; else - { - if (get_attr_mode (insn) == MODE_SI) - return "sal{l}\t{%2, %k0|%k0, %2}"; - else - return "sal{b}\t{%2, %0|%0, %2}"; - } + return "sal{}\t{%2, %0|%0, %2}"; } } [(set (attr "type") @@ -10543,47 +10102,42 @@ (const_int 0))))) (const_string "0") (const_string "*"))) - (set_attr "mode" "QI,SI")]) + (set_attr "mode" "")]) -;; This pattern can't accept a variable shift count, since shifts by -;; zero don't affect the flags. We assume that shifts by constant -;; zero are optimized away. -(define_insn "*ashlqi3_cmp" +(define_insn "*ashlsi3_cmp_zext" [(set (reg FLAGS_REG) (compare - (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0") + (ashift:SI (match_operand:SI 1 "register_operand" "0") (match_operand:QI 2 "const_1_to_31_operand" "I")) (const_int 0))) - (set (match_operand:QI 0 "nonimmediate_operand" "=qm") - (ashift:QI (match_dup 1) (match_dup 2)))] - "(optimize_function_for_size_p (cfun) - || !TARGET_PARTIAL_FLAG_REG_STALL - || (operands[2] == const1_rtx - && (TARGET_SHIFT1 - || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0]))))) + (set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI (ashift:SI (match_dup 1) (match_dup 2))))] + "TARGET_64BIT + && (optimize_function_for_size_p (cfun) + || !TARGET_PARTIAL_FLAG_REG_STALL + || (operands[2] == const1_rtx + && (TARGET_SHIFT1 + || TARGET_DOUBLE_WITH_ADD))) && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFT, QImode, operands)" + && ix86_binary_operator_ok (ASHIFT, SImode, operands)" { switch (get_attr_type (insn)) { case TYPE_ALU: gcc_assert (operands[2] == const1_rtx); - return "add{b}\t%0, %0"; + return "add{l}\t%k0, %k0"; default: - if (REG_P (operands[2])) - return "sal{b}\t{%b2, %0|%0, %b2}"; - else if (operands[2] == const1_rtx - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{b}\t%0"; + if (operands[2] == const1_rtx + && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) + return "sal{l}\t%k0"; else - return "sal{b}\t{%2, %0|%0, %2}"; + return "sal{l}\t{%2, %k0|%k0, %2}"; } } [(set (attr "type") - (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") - (const_int 0)) - (match_operand 0 "register_operand" "")) + (cond [(and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") + (const_int 0)) (match_operand 2 "const1_operand" "")) (const_string "alu") ] @@ -10597,37 +10151,35 @@ (const_int 0))))) (const_string "0") (const_string "*"))) - (set_attr "mode" "QI")]) + (set_attr "mode" "SI")]) -(define_insn "*ashlqi3_cconly" +(define_insn "*ashl3_cconly" [(set (reg FLAGS_REG) (compare - (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_1_to_31_operand" "I")) + (ashift:SWI (match_operand:SWI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "" "")) (const_int 0))) - (clobber (match_scratch:QI 0 "=q"))] + (clobber (match_scratch:SWI 0 "="))] "(optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_FLAG_REG_STALL || (operands[2] == const1_rtx && (TARGET_SHIFT1 || TARGET_DOUBLE_WITH_ADD))) && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFT, QImode, operands)" + && ix86_binary_operator_ok (ASHIFT, mode, operands)" { switch (get_attr_type (insn)) { case TYPE_ALU: gcc_assert (operands[2] == const1_rtx); - return "add{b}\t%0, %0"; + return "add{}\t%0, %0"; default: - if (REG_P (operands[2])) - return "sal{b}\t{%b2, %0|%0, %b2}"; - else if (operands[2] == const1_rtx - && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{b}\t%0"; + if (operands[2] == const1_rtx + && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) + return "sal{}\t%0"; else - return "sal{b}\t{%2, %0|%0, %2}"; + return "sal{}\t{%2, %0|%0, %2}"; } } [(set (attr "type") @@ -10647,7 +10199,7 @@ (const_int 0))))) (const_string "0") (const_string "*"))) - (set_attr "mode" "QI")]) + (set_attr "mode" "")]) ;; See comment above `ashldi3' about how this works. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 09aa4cc63ecf..51895eeccd3d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -308,7 +308,7 @@ * gcc.c-torture/execute/pr43629.c: New testcase. 2010-04-01 Janne Blomqvist - Dominique d'Humieres + Dominique d'Humieres PR libfortran/43605 * gfortran.dg/ftell_3.f90: Enhance test case by reading more.