From: Uros Bizjak Date: Tue, 6 Oct 2009 13:52:59 +0000 (+0200) Subject: i386.md (SWI48, SDWI, DWI): New mode iterators. X-Git-Tag: releases/gcc-4.5.0~3083 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d2407a7aca3b4db2234d5c27ff1ce43074a84246;p=thirdparty%2Fgcc.git i386.md (SWI48, SDWI, DWI): New mode iterators. * config/i386/i386.md (SWI48, SDWI, DWI): New mode iterators. (DWIH, g, di, doubleint_general_operand): New mode attributes. (general_operand): Handle TI mode. (add3): Macroize expander from add{qi,hi,si,di,ti}3 patterns using SDWI mode iterator. (*add3_doubleword): New insn_and_split pattern. Macroize pattern from *add{di,ti}3_1 patterns and corresponding splitters using SDWI mode iterator. (add3_carry): Macroize insn from add{qi,hi,si,di}3_carry patterns using SWI mode iterator. (*add3_cc): Macroize insn from add{si,di}3_cc patterns using SWI48 mode iterator. (*add_1): Ditto from add{si,di}_1 patterns. (*add_2): Ditto from add{si,di}_2 patterns. (*add_3): Ditto from add{si,di}_3 patterns. (*add_5): Ditto from add{si,di}_5 patterns. (sub3): Macroize expander from sub{qi,hi,si,di,ti}3 patterns using SDWI mode iterator. (*sub3_doubleword): New insn_and_split pattern. Macroize pattern from *sub{di,ti}3_1 patterns and corresponding splitters using SDWI mode iterator. (sub3_carry): Macroize insn from sub{qi,hi,si,di}3_carry patterns using SWI mode iterator. (*sub_1): Ditto from from sub{qi,hi,si,di}_1 patterns. (*sub_2): Ditto from sub{qi,hi,si,di}_2 patterns. (*sub_3): Ditto from sub{qi,hi,si,di}_3 patterns. (xf3): Macroize expander from addxf3 and subxf3 patterns using plusminus code iterator. (3): Macroize expander from add3 and sub3 patterns using plusminus code iterator. * config/i386/i386.c (override_options): Update call to gen_subdi_carry_rex64 for renamed function. (ix86_expand_int_addcc): Update calls to gen_subdi3_carry_rex64 and gen_adddi3_carry_rex64 for renamed functions. Use indirect calls to instruction expanders. From-SVN: r152495 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ae6f4630f7f7..f9c63e5f1e81 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,41 @@ +2009-10-06 Uros Bizjak + + * config/i386/i386.md (SWI48, SDWI, DWI): New mode iterators. + (DWIH, g, di, doubleint_general_operand): New mode attributes. + (general_operand): Handle TI mode. + (add3): Macroize expander from add{qi,hi,si,di,ti}3 patterns + using SDWI mode iterator. + (*add3_doubleword): New insn_and_split pattern. Macroize + pattern from *add{di,ti}3_1 patterns and corresponding splitters + using SDWI mode iterator. + (add3_carry): Macroize insn from add{qi,hi,si,di}3_carry + patterns using SWI mode iterator. + (*add3_cc): Macroize insn from add{si,di}3_cc patterns + using SWI48 mode iterator. + (*add_1): Ditto from add{si,di}_1 patterns. + (*add_2): Ditto from add{si,di}_2 patterns. + (*add_3): Ditto from add{si,di}_3 patterns. + (*add_5): Ditto from add{si,di}_5 patterns. + (sub3): Macroize expander from sub{qi,hi,si,di,ti}3 patterns + using SDWI mode iterator. + (*sub3_doubleword): New insn_and_split pattern. Macroize + pattern from *sub{di,ti}3_1 patterns and corresponding splitters + using SDWI mode iterator. + (sub3_carry): Macroize insn from sub{qi,hi,si,di}3_carry + patterns using SWI mode iterator. + (*sub_1): Ditto from from sub{qi,hi,si,di}_1 patterns. + (*sub_2): Ditto from sub{qi,hi,si,di}_2 patterns. + (*sub_3): Ditto from sub{qi,hi,si,di}_3 patterns. + (xf3): Macroize expander from addxf3 and subxf3 + patterns using plusminus code iterator. + (3): Macroize expander from add3 and + sub3 patterns using plusminus code iterator. + * config/i386/i386.c (override_options): Update call to + gen_subdi_carry_rex64 for renamed function. + (ix86_expand_int_addcc): Update calls to gen_subdi3_carry_rex64 + and gen_adddi3_carry_rex64 for renamed functions. Use indirect + calls to instruction expanders. + 2009-10-06 Martin Jambor PR bootstrap/41395 @@ -215,8 +253,8 @@ 2009-10-05 Ramana Radhakrishnan - * config/arm/arm.c (arm_override_options): Really initialize - flag_dwarf2_cfi_asm to 0. + * config/arm/arm.c (arm_override_options): Really initialize + flag_dwarf2_cfi_asm to 0. 2009-10-05 Doug Kwan diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 9df01ba23dcc..9da427faaa76 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -3394,7 +3394,7 @@ override_options (bool main_args_p) ix86_gen_pop1 = gen_popdi1; ix86_gen_add3 = gen_adddi3; ix86_gen_sub3 = gen_subdi3; - ix86_gen_sub3_carry = gen_subdi3_carry_rex64; + ix86_gen_sub3_carry = gen_subdi3_carry; ix86_gen_one_cmpl2 = gen_one_cmpldi2; ix86_gen_monitor = gen_sse3_monitor64; ix86_gen_andsp = gen_anddi3; @@ -16171,6 +16171,7 @@ int ix86_expand_int_addcc (rtx operands[]) { enum rtx_code code = GET_CODE (operands[1]); + rtx (*insn)(rtx, rtx, rtx, rtx); rtx compare_op; rtx val = const0_rtx; bool fpcmp = false; @@ -16211,16 +16212,16 @@ ix86_expand_int_addcc (rtx operands[]) switch (GET_MODE (operands[0])) { case QImode: - emit_insn (gen_subqi3_carry (operands[0], operands[2], val, compare_op)); + insn = gen_subqi3_carry; break; case HImode: - emit_insn (gen_subhi3_carry (operands[0], operands[2], val, compare_op)); + insn = gen_subhi3_carry; break; case SImode: - emit_insn (gen_subsi3_carry (operands[0], operands[2], val, compare_op)); + insn = gen_subsi3_carry; break; case DImode: - emit_insn (gen_subdi3_carry_rex64 (operands[0], operands[2], val, compare_op)); + insn = gen_subdi3_carry; break; default: gcc_unreachable (); @@ -16231,21 +16232,23 @@ ix86_expand_int_addcc (rtx operands[]) switch (GET_MODE (operands[0])) { case QImode: - emit_insn (gen_addqi3_carry (operands[0], operands[2], val, compare_op)); + insn = gen_addqi3_carry; break; case HImode: - emit_insn (gen_addhi3_carry (operands[0], operands[2], val, compare_op)); + insn = gen_addhi3_carry; break; case SImode: - emit_insn (gen_addsi3_carry (operands[0], operands[2], val, compare_op)); + insn = gen_addsi3_carry; break; case DImode: - emit_insn (gen_adddi3_carry_rex64 (operands[0], operands[2], val, compare_op)); + insn = gen_adddi3_carry; break; default: gcc_unreachable (); } } + emit_insn (insn (operands[0], operands[2], val, compare_op)); + return 1; /* DONE */ } diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 27800804eca9..10c2dc6fd73b 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -708,6 +708,23 @@ ;; Single word integer modes without QImode. (define_mode_iterator SWI248 [HI SI (DI "TARGET_64BIT")]) +;; Single word integer modes without QImode and HImode. +(define_mode_iterator SWI48 [SI (DI "TARGET_64BIT")]) + +;; All single and double word integer modes. +(define_mode_iterator SDWI [(QI "TARGET_QIMODE_MATH") + (HI "TARGET_HIMODE_MATH") + SI + DI + (TI "TARGET_64BIT")]) + +;; Double word integer modes. +(define_mode_iterator DWI [(DI "!TARGET_64BIT") + (TI "TARGET_64BIT")]) + +;; Half mode for double word integer modes. +(define_mode_attr DWIH [(DI "SI") (TI "DI")]) + ;; Instruction suffix for integer modes. (define_mode_attr imodesuffix [(QI "b") (HI "w") (SI "l") (DI "q")]) @@ -717,12 +734,24 @@ ;; Immediate operand constraint for integer modes. (define_mode_attr i [(QI "n") (HI "n") (SI "i") (DI "e")]) +;; General operand constraint for word modes. +(define_mode_attr g [(SI "g") (DI "rme")]) + +;; Immediate operand constraint for double integer modes. +(define_mode_attr di [(DI "iF") (TI "e")]) + ;; General operand predicate for integer modes. (define_mode_attr general_operand [(QI "general_operand") (HI "general_operand") (SI "general_operand") - (DI "x86_64_general_operand")]) + (DI "x86_64_general_operand") + (TI "x86_64_general_operand")]) + +;; General operand predicate for double integer modes. +(define_mode_attr doubleint_general_operand + [(DI "general_operand") + (TI "x86_64_general_operand")]) ;; SSE and x87 SFmode and DFmode floating point modes (define_mode_iterator MODEF [SF DF]) @@ -2994,7 +3023,6 @@ [(set (match_dup 0) (match_dup 2))]) - ;; %%% Kill this when call knows how to work this out. (define_split [(set (match_operand:SF 0 "push_operand" "") @@ -6046,195 +6074,57 @@ ;; Add instructions -;; %%% splits for addditi3 - -(define_expand "addti3" - [(set (match_operand:TI 0 "nonimmediate_operand" "") - (plus:TI (match_operand:TI 1 "nonimmediate_operand" "") - (match_operand:TI 2 "x86_64_general_operand" "")))] - "TARGET_64BIT" - "ix86_expand_binary_operator (PLUS, TImode, operands); DONE;") - -(define_insn "*addti3_1" - [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o") - (plus:TI (match_operand:TI 1 "nonimmediate_operand" "%0,0") - (match_operand:TI 2 "x86_64_general_operand" "roe,re"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (PLUS, TImode, operands)" - "#") - -(define_split - [(set (match_operand:TI 0 "nonimmediate_operand" "") - (plus:TI (match_operand:TI 1 "nonimmediate_operand" "") - (match_operand:TI 2 "x86_64_general_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && reload_completed" - [(parallel [(set (reg:CC FLAGS_REG) (unspec:CC [(match_dup 1) (match_dup 2)] - UNSPEC_ADD_CARRY)) - (set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))]) - (parallel [(set (match_dup 3) - (plus:DI (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0)) - (match_dup 4)) - (match_dup 5))) - (clobber (reg:CC FLAGS_REG))])] - "split_ti (&operands[0], 3, &operands[0], &operands[3]);") - -;; %%% splits for addsidi3 -; [(set (match_operand:DI 0 "nonimmediate_operand" "") -; (plus:DI (match_operand:DI 1 "general_operand" "") -; (zero_extend:DI (match_operand:SI 2 "general_operand" ""))))] - -(define_expand "adddi3" - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (plus:DI (match_operand:DI 1 "nonimmediate_operand" "") - (match_operand:DI 2 "x86_64_general_operand" "")))] +(define_expand "add3" + [(set (match_operand:SDWI 0 "nonimmediate_operand" "") + (plus:SDWI (match_operand:SDWI 1 "nonimmediate_operand" "") + (match_operand:SDWI 2 "" "")))] "" - "ix86_expand_binary_operator (PLUS, DImode, operands); DONE;") - -(define_insn "*adddi3_1" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o") - (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0") - (match_operand:DI 2 "general_operand" "roiF,riF"))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)" - "#") + "ix86_expand_binary_operator (PLUS, mode, operands); DONE;") -(define_split - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (plus:DI (match_operand:DI 1 "nonimmediate_operand" "") - (match_operand:DI 2 "general_operand" ""))) +(define_insn_and_split "*add3_doubleword" + [(set (match_operand:DWI 0 "nonimmediate_operand" "=r,o") + (plus:DWI + (match_operand:DWI 1 "nonimmediate_operand" "%0,0") + (match_operand:DWI 2 "" "ro,r"))) (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT && reload_completed" - [(parallel [(set (reg:CC FLAGS_REG) (unspec:CC [(match_dup 1) (match_dup 2)] - UNSPEC_ADD_CARRY)) - (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]) + "ix86_binary_operator_ok (PLUS, mode, operands)" + "#" + "reload_completed" + [(parallel [(set (reg:CC FLAGS_REG) + (unspec:CC [(match_dup 1) (match_dup 2)] + UNSPEC_ADD_CARRY)) + (set (match_dup 0) + (plus: (match_dup 1) (match_dup 2)))]) (parallel [(set (match_dup 3) - (plus:SI (plus:SI (ltu:SI (reg:CC FLAGS_REG) (const_int 0)) - (match_dup 4)) - (match_dup 5))) + (plus: + (plus: + (ltu: (reg:CC FLAGS_REG) (const_int 0)) + (match_dup 4)) + (match_dup 5))) (clobber (reg:CC FLAGS_REG))])] - "split_di (&operands[0], 3, &operands[0], &operands[3]);") + "split_ (&operands[0], 3, &operands[0], &operands[3]);") -(define_insn "adddi3_carry_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r") - (plus:DI (plus:DI (match_operand:DI 3 "ix86_carry_flag_operator" "") - (match_operand:DI 1 "nonimmediate_operand" "%0,0")) - (match_operand:DI 2 "x86_64_general_operand" "re,rm"))) +(define_insn "add3_carry" + [(set (match_operand:SWI 0 "nonimmediate_operand" "=m,") + (plus:SWI + (plus:SWI (match_operand:SWI 3 "ix86_carry_flag_operator" "") + (match_operand:SWI 1 "nonimmediate_operand" "%0,0")) + (match_operand:SWI 2 "" ",m"))) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)" - "adc{q}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "mode" "DI")]) - -(define_insn "*adddi3_cc_rex64" - [(set (reg:CC FLAGS_REG) - (unspec:CC [(match_operand:DI 1 "nonimmediate_operand" "%0,0") - (match_operand:DI 2 "x86_64_general_operand" "re,rm")] - UNSPEC_ADD_CARRY)) - (set (match_operand:DI 0 "nonimmediate_operand" "=rm,r") - (plus:DI (match_dup 1) (match_dup 2)))] - "TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)" - "add{q}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "DI")]) - -(define_insn "*3_cc_overflow" - [(set (reg:CCC FLAGS_REG) - (compare:CCC - (plusminus:SWI - (match_operand:SWI 1 "nonimmediate_operand" "0,0") - (match_operand:SWI 2 "" ",m")) - (match_dup 1))) - (set (match_operand:SWI 0 "nonimmediate_operand" "=m,") - (plusminus:SWI (match_dup 1) (match_dup 2)))] - "ix86_binary_operator_ok (, mode, operands)" - "{}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "")]) - -(define_insn "*add3_cconly_overflow" - [(set (reg:CCC FLAGS_REG) - (compare:CCC - (plus:SWI (match_operand:SWI 1 "nonimmediate_operand" "%0") - (match_operand:SWI 2 "" "m")) - (match_dup 1))) - (clobber (match_scratch:SWI 0 "="))] "ix86_binary_operator_ok (PLUS, mode, operands)" - "add{}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "")]) - -(define_insn "*sub3_cconly_overflow" - [(set (reg:CCC FLAGS_REG) - (compare:CCC - (minus:SWI (match_operand:SWI 0 "nonimmediate_operand" "m,") - (match_operand:SWI 1 "" ",m")) - (match_dup 0)))] - "" - "cmp{}\t{%1, %0|%0, %1}" - [(set_attr "type" "icmp") - (set_attr "mode" "")]) - -(define_insn "*si3_zext_cc_overflow" - [(set (reg:CCC FLAGS_REG) - (compare:CCC - (plusminus:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:SI 2 "general_operand" "g")) - (match_dup 1))) - (set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI (plusminus:SI (match_dup 1) (match_dup 2))))] - "TARGET_64BIT && ix86_binary_operator_ok (, SImode, operands)" - "{l}\t{%2, %k0|%k0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "SI")]) - -(define_insn "addqi3_carry" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q") - (plus:QI (plus:QI (match_operand:QI 3 "ix86_carry_flag_operator" "") - (match_operand:QI 1 "nonimmediate_operand" "%0,0")) - (match_operand:QI 2 "general_operand" "qn,qm"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (PLUS, QImode, operands)" - "adc{b}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "mode" "QI")]) - -(define_insn "addhi3_carry" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") - (plus:HI (plus:HI (match_operand:HI 3 "ix86_carry_flag_operator" "") - (match_operand:HI 1 "nonimmediate_operand" "%0,0")) - (match_operand:HI 2 "general_operand" "rn,rm"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (PLUS, HImode, operands)" - "adc{w}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "mode" "HI")]) - -(define_insn "addsi3_carry" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") - (plus:SI (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "") - (match_operand:SI 1 "nonimmediate_operand" "%0,0")) - (match_operand:SI 2 "general_operand" "ri,rm"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (PLUS, SImode, operands)" - "adc{l}\t{%2, %0|%0, %2}" + "adc{}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") (set_attr "use_carry" "1") (set_attr "pent_pair" "pu") - (set_attr "mode" "SI")]) + (set_attr "mode" "")]) (define_insn "*addsi3_carry_zext" [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI - (plus:SI (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "") - (match_operand:SI 1 "nonimmediate_operand" "%0")) - (match_operand:SI 2 "general_operand" "g")))) + (zero_extend:DI + (plus:SI + (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "") + (match_operand:SI 1 "nonimmediate_operand" "%0")) + (match_operand:SI 2 "general_operand" "g")))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)" "adc{l}\t{%2, %k0|%k0, %2}" @@ -6243,23 +6133,25 @@ (set_attr "pent_pair" "pu") (set_attr "mode" "SI")]) -(define_insn "*addsi3_cc" +(define_insn "*add3_cc" [(set (reg:CC FLAGS_REG) - (unspec:CC [(match_operand:SI 1 "nonimmediate_operand" "%0,0") - (match_operand:SI 2 "general_operand" "ri,rm")] - UNSPEC_ADD_CARRY)) - (set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") - (plus:SI (match_dup 1) (match_dup 2)))] - "ix86_binary_operator_ok (PLUS, SImode, operands)" - "add{l}\t{%2, %0|%0, %2}" + (unspec:CC + [(match_operand:SWI48 1 "nonimmediate_operand" "%0,0") + (match_operand:SWI48 2 "" "r,rm")] + UNSPEC_ADD_CARRY)) + (set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r") + (plus:SWI48 (match_dup 1) (match_dup 2)))] + "ix86_binary_operator_ok (PLUS, mode, operands)" + "add{}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") - (set_attr "mode" "SI")]) + (set_attr "mode" "")]) (define_insn "addqi3_cc" [(set (reg:CC FLAGS_REG) - (unspec:CC [(match_operand:QI 1 "nonimmediate_operand" "%0,0") - (match_operand:QI 2 "general_operand" "qn,qm")] - UNSPEC_ADD_CARRY)) + (unspec:CC + [(match_operand:QI 1 "nonimmediate_operand" "%0,0") + (match_operand:QI 2 "general_operand" "qn,qm")] + UNSPEC_ADD_CARRY)) (set (match_operand:QI 0 "nonimmediate_operand" "=qm,q") (plus:QI (match_dup 1) (match_dup 2)))] "ix86_binary_operator_ok (PLUS, QImode, operands)" @@ -6267,263 +6159,138 @@ [(set_attr "type" "alu") (set_attr "mode" "QI")]) -(define_expand "addsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (plus:SI (match_operand:SI 1 "nonimmediate_operand" "") - (match_operand:SI 2 "general_operand" "")))] - "" - "ix86_expand_binary_operator (PLUS, SImode, operands); DONE;") - -(define_insn "*lea_1" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operand:SI 1 "no_seg_address_operand" "p"))] - "!TARGET_64BIT" - "lea{l}\t{%a1, %0|%0, %a1}" - [(set_attr "type" "lea") - (set_attr "mode" "SI")]) - -(define_insn "*lea_1_rex64" - [(set (match_operand:SI 0 "register_operand" "=r") - (subreg:SI (match_operand:DI 1 "no_seg_address_operand" "p") 0))] - "TARGET_64BIT" - "lea{l}\t{%a1, %0|%0, %a1}" - [(set_attr "type" "lea") - (set_attr "mode" "SI")]) +(define_insn "*add3_cconly_overflow" + [(set (reg:CCC FLAGS_REG) + (compare:CCC + (plus:SWI + (match_operand:SWI 1 "nonimmediate_operand" "%0") + (match_operand:SWI 2 "" "m")) + (match_dup 1))) + (clobber (match_scratch:SWI 0 "="))] + "ix86_binary_operator_ok (PLUS, mode, operands)" + "add{}\t{%2, %0|%0, %2}" + [(set_attr "type" "alu") + (set_attr "mode" "")]) -(define_insn "*lea_1_zext" - [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI - (subreg:SI (match_operand:DI 1 "no_seg_address_operand" "p") 0)))] - "TARGET_64BIT" - "lea{l}\t{%a1, %k0|%k0, %a1}" - [(set_attr "type" "lea") - (set_attr "mode" "SI")]) +(define_insn "*add_1" + [(set (match_operand:SWI48 0 "nonimmediate_operand" "=r,rm,r,r") + (plus:SWI48 + (match_operand:SWI48 1 "nonimmediate_operand" "%0,0,r,r") + (match_operand:SWI48 2 "" ",r,0,l"))) + (clobber (reg:CC FLAGS_REG))] + "ix86_binary_operator_ok (PLUS, mode, operands)" +{ + switch (get_attr_type (insn)) + { + case TYPE_LEA: + operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0)); + return "lea{}\t{%a2, %0|%0, %a2}"; -(define_insn "*lea_2_rex64" - [(set (match_operand:DI 0 "register_operand" "=r") - (match_operand:DI 1 "no_seg_address_operand" "p"))] - "TARGET_64BIT" - "lea{q}\t{%a1, %0|%0, %a1}" - [(set_attr "type" "lea") - (set_attr "mode" "DI")]) + case TYPE_INCDEC: + gcc_assert (rtx_equal_p (operands[0], operands[1])); + if (operands[2] == const1_rtx) + return "inc{}\t%0"; + else + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{}\t%0"; + } -;; The lea patterns for non-Pmodes needs to be matched by several -;; insns converted to real lea by splitters. + default: + /* Use add as much as possible to replace lea for AGU optimization. */ + if (which_alternative == 2 && TARGET_OPT_AGU) + return "add{}\t{%1, %0|%0, %1}"; + + gcc_assert (rtx_equal_p (operands[0], operands[1])); -(define_insn_and_split "*lea_general_1" - [(set (match_operand 0 "register_operand" "=r") - (plus (plus (match_operand 1 "index_register_operand" "l") - (match_operand 2 "register_operand" "r")) - (match_operand 3 "immediate_operand" "i")))] - "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode - || (TARGET_64BIT && GET_MODE (operands[0]) == SImode)) - && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && GET_MODE (operands[0]) == GET_MODE (operands[1]) - && GET_MODE (operands[0]) == GET_MODE (operands[2]) - && (GET_MODE (operands[0]) == GET_MODE (operands[3]) - || GET_MODE (operands[3]) == VOIDmode)" - "#" - "&& reload_completed" - [(const_int 0)] -{ - rtx pat; - operands[0] = gen_lowpart (SImode, operands[0]); - operands[1] = gen_lowpart (Pmode, operands[1]); - operands[2] = gen_lowpart (Pmode, operands[2]); - operands[3] = gen_lowpart (Pmode, operands[3]); - pat = gen_rtx_PLUS (Pmode, gen_rtx_PLUS (Pmode, operands[1], operands[2]), - operands[3]); - if (Pmode != SImode) - pat = gen_rtx_SUBREG (SImode, pat, 0); - emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat)); - DONE; + /* Make things pretty and `subl $4,%eax' rather than `addl $-4,%eax'. + Exceptions: -128 encodes smaller than 128, so swap sign and op. */ + if (CONST_INT_P (operands[2]) + /* Avoid overflows. */ + && (mode != DImode + || ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))) + && (INTVAL (operands[2]) == 128 + || (INTVAL (operands[2]) < 0 + && INTVAL (operands[2]) != -128))) + { + operands[2] = GEN_INT (-INTVAL (operands[2])); + return "sub{}\t{%2, %0|%0, %2}"; + } + return "add{}\t{%2, %0|%0, %2}"; + } } - [(set_attr "type" "lea") - (set_attr "mode" "SI")]) + [(set (attr "type") + (cond [(and (eq_attr "alternative" "2") + (eq (symbol_ref "TARGET_OPT_AGU") (const_int 0))) + (const_string "lea") + (eq_attr "alternative" "3") + (const_string "lea") + ; Current assemblers are broken and do not allow @GOTOFF in + ; ought but a memory context. + (match_operand:SWI48 2 "pic_symbolic_operand" "") + (const_string "lea") + (match_operand:SWI48 2 "incdec_operand" "") + (const_string "incdec") + ] + (const_string "alu"))) + (set (attr "length_immediate") + (if_then_else + (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) + (const_string "1") + (const_string "*"))) + (set_attr "mode" "")]) -(define_insn_and_split "*lea_general_1_zext" - [(set (match_operand:DI 0 "register_operand" "=r") +;; It may seem that nonimmediate operand is proper one for operand 1. +;; The addsi_1 pattern allows nonimmediate operand at that place and +;; we take care in ix86_binary_operator_ok to not allow two memory +;; operands so proper swapping will be done in reload. This allow +;; patterns constructed from addsi_1 to match. + +(define_insn "*addsi_1_zext" + [(set (match_operand:DI 0 "register_operand" "=r,r") (zero_extend:DI - (plus:SI (plus:SI (match_operand:SI 1 "index_register_operand" "l") - (match_operand:SI 2 "register_operand" "r")) - (match_operand:SI 3 "immediate_operand" "i"))))] - "TARGET_64BIT" - "#" - "&& reload_completed" - [(set (match_dup 0) - (zero_extend:DI (subreg:SI (plus:DI (plus:DI (match_dup 1) - (match_dup 2)) - (match_dup 3)) 0)))] -{ - operands[1] = gen_lowpart (Pmode, operands[1]); - operands[2] = gen_lowpart (Pmode, operands[2]); - operands[3] = gen_lowpart (Pmode, operands[3]); -} - [(set_attr "type" "lea") - (set_attr "mode" "SI")]) - -(define_insn_and_split "*lea_general_2" - [(set (match_operand 0 "register_operand" "=r") - (plus (mult (match_operand 1 "index_register_operand" "l") - (match_operand 2 "const248_operand" "i")) - (match_operand 3 "nonmemory_operand" "ri")))] - "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode - || (TARGET_64BIT && GET_MODE (operands[0]) == SImode)) - && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && GET_MODE (operands[0]) == GET_MODE (operands[1]) - && (GET_MODE (operands[0]) == GET_MODE (operands[3]) - || GET_MODE (operands[3]) == VOIDmode)" - "#" - "&& reload_completed" - [(const_int 0)] -{ - rtx pat; - operands[0] = gen_lowpart (SImode, operands[0]); - operands[1] = gen_lowpart (Pmode, operands[1]); - operands[3] = gen_lowpart (Pmode, operands[3]); - pat = gen_rtx_PLUS (Pmode, gen_rtx_MULT (Pmode, operands[1], operands[2]), - operands[3]); - if (Pmode != SImode) - pat = gen_rtx_SUBREG (SImode, pat, 0); - emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat)); - DONE; -} - [(set_attr "type" "lea") - (set_attr "mode" "SI")]) - -(define_insn_and_split "*lea_general_2_zext" - [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI - (plus:SI (mult:SI (match_operand:SI 1 "index_register_operand" "l") - (match_operand:SI 2 "const248_operand" "n")) - (match_operand:SI 3 "nonmemory_operand" "ri"))))] - "TARGET_64BIT" - "#" - "&& reload_completed" - [(set (match_dup 0) - (zero_extend:DI (subreg:SI (plus:DI (mult:DI (match_dup 1) - (match_dup 2)) - (match_dup 3)) 0)))] -{ - operands[1] = gen_lowpart (Pmode, operands[1]); - operands[3] = gen_lowpart (Pmode, operands[3]); -} - [(set_attr "type" "lea") - (set_attr "mode" "SI")]) - -(define_insn_and_split "*lea_general_3" - [(set (match_operand 0 "register_operand" "=r") - (plus (plus (mult (match_operand 1 "index_register_operand" "l") - (match_operand 2 "const248_operand" "i")) - (match_operand 3 "register_operand" "r")) - (match_operand 4 "immediate_operand" "i")))] - "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode - || (TARGET_64BIT && GET_MODE (operands[0]) == SImode)) - && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && GET_MODE (operands[0]) == GET_MODE (operands[1]) - && GET_MODE (operands[0]) == GET_MODE (operands[3])" - "#" - "&& reload_completed" - [(const_int 0)] -{ - rtx pat; - operands[0] = gen_lowpart (SImode, operands[0]); - operands[1] = gen_lowpart (Pmode, operands[1]); - operands[3] = gen_lowpart (Pmode, operands[3]); - operands[4] = gen_lowpart (Pmode, operands[4]); - pat = gen_rtx_PLUS (Pmode, - gen_rtx_PLUS (Pmode, gen_rtx_MULT (Pmode, operands[1], - operands[2]), - operands[3]), - operands[4]); - if (Pmode != SImode) - pat = gen_rtx_SUBREG (SImode, pat, 0); - emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat)); - DONE; -} - [(set_attr "type" "lea") - (set_attr "mode" "SI")]) - -(define_insn_and_split "*lea_general_3_zext" - [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI - (plus:SI (plus:SI (mult:SI - (match_operand:SI 1 "index_register_operand" "l") - (match_operand:SI 2 "const248_operand" "n")) - (match_operand:SI 3 "register_operand" "r")) - (match_operand:SI 4 "immediate_operand" "i"))))] - "TARGET_64BIT" - "#" - "&& reload_completed" - [(set (match_dup 0) - (zero_extend:DI (subreg:SI (plus:DI (plus:DI (mult:DI (match_dup 1) - (match_dup 2)) - (match_dup 3)) - (match_dup 4)) 0)))] -{ - operands[1] = gen_lowpart (Pmode, operands[1]); - operands[3] = gen_lowpart (Pmode, operands[3]); - operands[4] = gen_lowpart (Pmode, operands[4]); -} - [(set_attr "type" "lea") - (set_attr "mode" "SI")]) - -(define_insn "*adddi_1_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r,r") - (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,r,r") - (match_operand:DI 2 "x86_64_general_operand" "rme,re,0,le"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)" + (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,r") + (match_operand:SI 2 "general_operand" "g,li")))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)" { switch (get_attr_type (insn)) { case TYPE_LEA: operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0)); - return "lea{q}\t{%a2, %0|%0, %a2}"; + return "lea{l}\t{%a2, %k0|%k0, %a2}"; case TYPE_INCDEC: - gcc_assert (rtx_equal_p (operands[0], operands[1])); if (operands[2] == const1_rtx) - return "inc{q}\t%0"; + return "inc{l}\t%k0"; else { gcc_assert (operands[2] == constm1_rtx); - return "dec{q}\t%0"; + return "dec{l}\t%k0"; } default: - /* Use add as much as possible to replace lea for AGU optimization. */ - if (which_alternative == 2 && TARGET_OPT_AGU) - return "add{q}\t{%1, %0|%0, %1}"; - - gcc_assert (rtx_equal_p (operands[0], operands[1])); - - /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. + /* Make things pretty and `subl $4,%eax' rather than `addl $-4,%eax'. Exceptions: -128 encodes smaller than 128, so swap sign and op. */ if (CONST_INT_P (operands[2]) - /* Avoid overflows. */ - && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1))) && (INTVAL (operands[2]) == 128 || (INTVAL (operands[2]) < 0 && INTVAL (operands[2]) != -128))) { operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{q}\t{%2, %0|%0, %2}"; + return "sub{l}\t{%2, %k0|%k0, %2}"; } - return "add{q}\t{%2, %0|%0, %2}"; + return "add{l}\t{%2, %k0|%k0, %2}"; } } [(set (attr "type") - (cond [(and (eq_attr "alternative" "2") - (eq (symbol_ref "TARGET_OPT_AGU") (const_int 0))) + (cond [(eq_attr "alternative" "1") (const_string "lea") - (eq_attr "alternative" "3") - (const_string "lea") ; Current assemblers are broken and do not allow @GOTOFF in ; ought but a memory context. - (match_operand:DI 2 "pic_symbolic_operand" "") + (match_operand:SI 2 "pic_symbolic_operand" "") (const_string "lea") - (match_operand:DI 2 "incdec_operand" "") + (match_operand:SI 2 "incdec_operand" "") (const_string "incdec") ] (const_string "alu"))) @@ -6532,68 +6299,43 @@ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) (const_string "1") (const_string "*"))) - (set_attr "mode" "DI")]) + (set_attr "mode" "SI")]) -;; Convert lea to the lea pattern to avoid flags dependency. -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (plus:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "x86_64_nonmemory_operand" ""))) +(define_insn "*addhi_1" + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") + (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") + (match_operand:HI 2 "general_operand" "rn,rm"))) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && reload_completed - && ix86_lea_for_add_ok (PLUS, insn, operands)" - [(set (match_dup 0) - (plus:DI (match_dup 1) - (match_dup 2)))] - "") - -(define_insn "*adddi_2_rex64" - [(set (reg FLAGS_REG) - (compare - (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0") - (match_operand:DI 2 "x86_64_general_operand" "rme,re")) - (const_int 0))) - (set (match_operand:DI 0 "nonimmediate_operand" "=r,rm") - (plus:DI (match_dup 1) (match_dup 2)))] - "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (PLUS, DImode, operands) - /* Current assemblers are broken and do not allow @GOTOFF in - ought but a memory context. */ - && ! pic_symbolic_operand (operands[2], VOIDmode)" + "TARGET_PARTIAL_REG_STALL + && ix86_binary_operator_ok (PLUS, HImode, operands)" { switch (get_attr_type (insn)) { case TYPE_INCDEC: - gcc_assert (rtx_equal_p (operands[0], operands[1])); if (operands[2] == const1_rtx) - return "inc{q}\t%0"; + return "inc{w}\t%0"; else { gcc_assert (operands[2] == constm1_rtx); - return "dec{q}\t%0"; + return "dec{w}\t%0"; } default: - gcc_assert (rtx_equal_p (operands[0], operands[1])); - /* ???? We ought to handle there the 32bit case too - - do we need new constraint? */ - /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. + /* Make things pretty and `subw $4,%ax' rather than `addw $-4,%ax'. Exceptions: -128 encodes smaller than 128, so swap sign and op. */ if (CONST_INT_P (operands[2]) - /* Avoid overflows. */ - && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1))) && (INTVAL (operands[2]) == 128 || (INTVAL (operands[2]) < 0 && INTVAL (operands[2]) != -128))) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{q}\t{%2, %0|%0, %2}"; - } - return "add{q}\t{%2, %0|%0, %2}"; + { + operands[2] = GEN_INT (-INTVAL (operands[2])); + return "sub{w}\t{%2, %0|%0, %2}"; + } + return "add{w}\t{%2, %0|%0, %2}"; } } [(set (attr "type") - (if_then_else (match_operand:DI 2 "incdec_operand" "") + (if_then_else (match_operand:HI 2 "incdec_operand" "") (const_string "incdec") (const_string "alu"))) (set (attr "length_immediate") @@ -6601,159 +6343,102 @@ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) (const_string "1") (const_string "*"))) - (set_attr "mode" "DI")]) + (set_attr "mode" "HI")]) -(define_insn "*adddi_3_rex64" - [(set (reg FLAGS_REG) - (compare (neg:DI (match_operand:DI 2 "x86_64_general_operand" "rme")) - (match_operand:DI 1 "x86_64_general_operand" "%0"))) - (clobber (match_scratch:DI 0 "=r"))] - "TARGET_64BIT - && ix86_match_ccmode (insn, CCZmode) - && !(MEM_P (operands[1]) && MEM_P (operands[2])) - /* Current assemblers are broken and do not allow @GOTOFF in - ought but a memory context. */ - && ! pic_symbolic_operand (operands[2], VOIDmode)" +;; %%% After Dave's SUBREG_BYTE stuff goes in, re-enable incb %ah +;; type optimizations enabled by define-splits. This is not important +;; for PII, and in fact harmful because of partial register stalls. + +(define_insn "*addhi_1_lea" + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,r") + (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,r") + (match_operand:HI 2 "general_operand" "rn,rm,ln"))) + (clobber (reg:CC FLAGS_REG))] + "!TARGET_PARTIAL_REG_STALL + && ix86_binary_operator_ok (PLUS, HImode, operands)" { switch (get_attr_type (insn)) { + case TYPE_LEA: + return "#"; case TYPE_INCDEC: - gcc_assert (rtx_equal_p (operands[0], operands[1])); if (operands[2] == const1_rtx) - return "inc{q}\t%0"; + return "inc{w}\t%0"; else - { + { gcc_assert (operands[2] == constm1_rtx); - return "dec{q}\t%0"; + return "dec{w}\t%0"; } default: - gcc_assert (rtx_equal_p (operands[0], operands[1])); - /* ???? We ought to handle there the 32bit case too - - do we need new constraint? */ - /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. + /* Make things pretty and `subw $4,%ax' rather than `addw $-4,%ax'. Exceptions: -128 encodes smaller than 128, so swap sign and op. */ if (CONST_INT_P (operands[2]) - /* Avoid overflows. */ - && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1))) && (INTVAL (operands[2]) == 128 || (INTVAL (operands[2]) < 0 && INTVAL (operands[2]) != -128))) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{q}\t{%2, %0|%0, %2}"; - } - return "add{q}\t{%2, %0|%0, %2}"; + { + operands[2] = GEN_INT (-INTVAL (operands[2])); + return "sub{w}\t{%2, %0|%0, %2}"; + } + return "add{w}\t{%2, %0|%0, %2}"; } } [(set (attr "type") - (if_then_else (match_operand:DI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu"))) + (if_then_else (eq_attr "alternative" "2") + (const_string "lea") + (if_then_else (match_operand:HI 2 "incdec_operand" "") + (const_string "incdec") + (const_string "alu")))) (set (attr "length_immediate") (if_then_else (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) (const_string "1") (const_string "*"))) - (set_attr "mode" "DI")]) + (set_attr "mode" "HI,HI,SI")]) -; For comparisons against 1, -1 and 128, we may generate better code -; by converting cmp to add, inc or dec as done by peephole2. This pattern -; is matched then. We can't accept general immediate, because for -; case of overflows, the result is messed up. -; This pattern also don't hold of 0x8000000000000000, since the value overflows -; when negated. -; Also carry flag is reversed compared to cmp, so this conversion is valid -; only for comparisons not depending on it. -(define_insn "*adddi_4_rex64" - [(set (reg FLAGS_REG) - (compare (match_operand:DI 1 "nonimmediate_operand" "0") - (match_operand:DI 2 "x86_64_immediate_operand" "e"))) - (clobber (match_scratch:DI 0 "=rm"))] - "TARGET_64BIT - && ix86_match_ccmode (insn, CCGCmode)" +(define_insn "*addqi_1" + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r") + (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0") + (match_operand:QI 2 "general_operand" "qn,qmn,rn"))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_PARTIAL_REG_STALL + && ix86_binary_operator_ok (PLUS, QImode, operands)" { + int widen = (which_alternative == 2); switch (get_attr_type (insn)) { case TYPE_INCDEC: - if (operands[2] == constm1_rtx) - return "inc{q}\t%0"; + if (operands[2] == const1_rtx) + return widen ? "inc{l}\t%k0" : "inc{b}\t%0"; else - { - gcc_assert (operands[2] == const1_rtx); - return "dec{q}\t%0"; - } - - default: - gcc_assert (rtx_equal_p (operands[0], operands[1])); - /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. - Exceptions: -128 encodes smaller than 128, so swap sign and op. */ - if ((INTVAL (operands[2]) == -128 - || (INTVAL (operands[2]) > 0 - && INTVAL (operands[2]) != 128)) - /* Avoid overflows. */ - && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))) - return "sub{q}\t{%2, %0|%0, %2}"; - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "add{q}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (if_then_else (match_operand:DI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu"))) - (set (attr "length_immediate") - (if_then_else - (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) - (const_string "1") - (const_string "*"))) - (set_attr "mode" "DI")]) - -(define_insn "*adddi_5_rex64" - [(set (reg FLAGS_REG) - (compare - (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0") - (match_operand:DI 2 "x86_64_general_operand" "rme")) - (const_int 0))) - (clobber (match_scratch:DI 0 "=r"))] - "TARGET_64BIT - && ix86_match_ccmode (insn, CCGOCmode) - && !(MEM_P (operands[1]) && MEM_P (operands[2])) - /* Current assemblers are broken and do not allow @GOTOFF in - ought but a memory context. */ - && ! pic_symbolic_operand (operands[2], VOIDmode)" -{ - switch (get_attr_type (insn)) - { - case TYPE_INCDEC: - gcc_assert (rtx_equal_p (operands[0], operands[1])); - if (operands[2] == const1_rtx) - return "inc{q}\t%0"; - else - { - gcc_assert (operands[2] == constm1_rtx); - return "dec{q}\t%0"; + { + gcc_assert (operands[2] == constm1_rtx); + return widen ? "dec{l}\t%k0" : "dec{b}\t%0"; } default: - gcc_assert (rtx_equal_p (operands[0], operands[1])); - /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. + /* Make things pretty and `subb $4,%al' rather than `addb $-4,%al'. Exceptions: -128 encodes smaller than 128, so swap sign and op. */ if (CONST_INT_P (operands[2]) - /* Avoid overflows. */ - && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1))) && (INTVAL (operands[2]) == 128 || (INTVAL (operands[2]) < 0 && INTVAL (operands[2]) != -128))) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{q}\t{%2, %0|%0, %2}"; - } - return "add{q}\t{%2, %0|%0, %2}"; + { + operands[2] = GEN_INT (-INTVAL (operands[2])); + if (widen) + return "sub{l}\t{%2, %k0|%k0, %2}"; + else + return "sub{b}\t{%2, %0|%0, %2}"; + } + if (widen) + return "add{l}\t{%k2, %k0|%k0, %k2}"; + else + return "add{b}\t{%2, %0|%0, %2}"; } } [(set (attr "type") - (if_then_else (match_operand:DI 2 "incdec_operand" "") + (if_then_else (match_operand:QI 2 "incdec_operand" "") (const_string "incdec") (const_string "alu"))) (set (attr "length_immediate") @@ -6761,184 +6446,115 @@ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) (const_string "1") (const_string "*"))) - (set_attr "mode" "DI")]) - + (set_attr "mode" "QI,QI,SI")]) -(define_insn "*addsi_1" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r,r") - (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r,r") - (match_operand:SI 2 "general_operand" "g,ri,0,li"))) +;; %%% Potential partial reg stall on alternative 2. What to do? +(define_insn "*addqi_1_lea" + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r,r") + (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0,r") + (match_operand:QI 2 "general_operand" "qn,qmn,rn,ln"))) (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (PLUS, SImode, operands)" + "!TARGET_PARTIAL_REG_STALL + && ix86_binary_operator_ok (PLUS, QImode, operands)" { + int widen = (which_alternative == 2); switch (get_attr_type (insn)) { case TYPE_LEA: - operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0)); - return "lea{l}\t{%a2, %0|%0, %a2}"; - + return "#"; case TYPE_INCDEC: - gcc_assert (rtx_equal_p (operands[0], operands[1])); if (operands[2] == const1_rtx) - return "inc{l}\t%0"; + return widen ? "inc{l}\t%k0" : "inc{b}\t%0"; else { - gcc_assert (operands[2] == constm1_rtx); - return "dec{l}\t%0"; + gcc_assert (operands[2] == constm1_rtx); + return widen ? "dec{l}\t%k0" : "dec{b}\t%0"; } default: - /* Use add as much as possible to replace lea for AGU optimization. */ - if (which_alternative == 2 && TARGET_OPT_AGU) - return "add{l}\t{%1, %0|%0, %1}"; - - gcc_assert (rtx_equal_p (operands[0], operands[1])); - - /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. + /* Make things pretty and `subb $4,%al' rather than `addb $-4,%al'. Exceptions: -128 encodes smaller than 128, so swap sign and op. */ if (CONST_INT_P (operands[2]) && (INTVAL (operands[2]) == 128 || (INTVAL (operands[2]) < 0 && INTVAL (operands[2]) != -128))) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{l}\t{%2, %0|%0, %2}"; - } - return "add{l}\t{%2, %0|%0, %2}"; + { + operands[2] = GEN_INT (-INTVAL (operands[2])); + if (widen) + return "sub{l}\t{%2, %k0|%k0, %2}"; + else + return "sub{b}\t{%2, %0|%0, %2}"; + } + if (widen) + return "add{l}\t{%k2, %k0|%k0, %k2}"; + else + return "add{b}\t{%2, %0|%0, %2}"; } } [(set (attr "type") - (cond [(and (eq_attr "alternative" "2") - (eq (symbol_ref "TARGET_OPT_AGU") (const_int 0))) - (const_string "lea") - (eq_attr "alternative" "3") - (const_string "lea") - ; Current assemblers are broken and do not allow @GOTOFF in - ; ought but a memory context. - (match_operand:SI 2 "pic_symbolic_operand" "") - (const_string "lea") - (match_operand:SI 2 "incdec_operand" "") - (const_string "incdec") - ] - (const_string "alu"))) + (if_then_else (eq_attr "alternative" "3") + (const_string "lea") + (if_then_else (match_operand:QI 2 "incdec_operand" "") + (const_string "incdec") + (const_string "alu")))) (set (attr "length_immediate") (if_then_else (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) (const_string "1") (const_string "*"))) - (set_attr "mode" "SI")]) - -;; Convert lea to the lea pattern to avoid flags dependency. -(define_split - [(set (match_operand 0 "register_operand" "") - (plus (match_operand 1 "register_operand" "") - (match_operand 2 "nonmemory_operand" ""))) - (clobber (reg:CC FLAGS_REG))] - "reload_completed && ix86_lea_for_add_ok (PLUS, insn, operands)" - [(const_int 0)] -{ - rtx pat; - /* In -fPIC mode the constructs like (const (unspec [symbol_ref])) - may confuse gen_lowpart. */ - if (GET_MODE (operands[0]) != Pmode) - { - operands[1] = gen_lowpart (Pmode, operands[1]); - operands[2] = gen_lowpart (Pmode, operands[2]); - } - operands[0] = gen_lowpart (SImode, operands[0]); - pat = gen_rtx_PLUS (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; -}) + (set_attr "mode" "QI,QI,SI,SI")]) -;; It may seem that nonimmediate operand is proper one for operand 1. -;; The addsi_1 pattern allows nonimmediate operand at that place and -;; we take care in ix86_binary_operator_ok to not allow two memory -;; operands so proper swapping will be done in reload. This allow -;; patterns constructed from addsi_1 to match. -(define_insn "addsi_1_zext" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (zero_extend:DI - (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,r") - (match_operand:SI 2 "general_operand" "g,li")))) +(define_insn "*addqi_1_slp" + [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) + (plus:QI (match_dup 0) + (match_operand:QI 1 "general_operand" "qn,qnm"))) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)" + "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) + && !(MEM_P (operands[0]) && MEM_P (operands[1]))" { switch (get_attr_type (insn)) { - case TYPE_LEA: - operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0)); - return "lea{l}\t{%a2, %k0|%k0, %a2}"; - case TYPE_INCDEC: - if (operands[2] == const1_rtx) - return "inc{l}\t%k0"; + if (operands[1] == const1_rtx) + return "inc{b}\t%0"; else - { - gcc_assert (operands[2] == constm1_rtx); - return "dec{l}\t%k0"; + { + gcc_assert (operands[1] == constm1_rtx); + return "dec{b}\t%0"; } default: - /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. - Exceptions: -128 encodes smaller than 128, so swap sign and op. */ - if (CONST_INT_P (operands[2]) - && (INTVAL (operands[2]) == 128 - || (INTVAL (operands[2]) < 0 - && INTVAL (operands[2]) != -128))) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{l}\t{%2, %k0|%k0, %2}"; - } - return "add{l}\t{%2, %k0|%k0, %2}"; + /* Make things pretty and `subb $4,%al' rather than `addb $-4,%al'. */ + if (CONST_INT_P (operands[1]) + && INTVAL (operands[1]) < 0) + { + operands[1] = GEN_INT (-INTVAL (operands[1])); + return "sub{b}\t{%1, %0|%0, %1}"; + } + return "add{b}\t{%1, %0|%0, %1}"; } } [(set (attr "type") - (cond [(eq_attr "alternative" "1") - (const_string "lea") - ; Current assemblers are broken and do not allow @GOTOFF in - ; ought but a memory context. - (match_operand:SI 2 "pic_symbolic_operand" "") - (const_string "lea") - (match_operand:SI 2 "incdec_operand" "") - (const_string "incdec") - ] - (const_string "alu"))) - (set (attr "length_immediate") - (if_then_else - (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) - (const_string "1") - (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 - (plus:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "nonmemory_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 (plus:DI (match_dup 1) (match_dup 2)) 0)))] -{ - operands[1] = gen_lowpart (Pmode, operands[1]); - operands[2] = gen_lowpart (Pmode, operands[2]); -}) + (if_then_else (match_operand:QI 1 "incdec_operand" "") + (const_string "incdec") + (const_string "alu1"))) + (set (attr "memory") + (if_then_else (match_operand 1 "memory_operand" "") + (const_string "load") + (const_string "none"))) + (set_attr "mode" "QI")]) -(define_insn "*addsi_2" +(define_insn "*add_2" [(set (reg FLAGS_REG) (compare - (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0") - (match_operand:SI 2 "general_operand" "g,ri")) + (plus:SWI48 + (match_operand:SWI48 1 "nonimmediate_operand" "%0,0") + (match_operand:SWI48 2 "" ",r")) (const_int 0))) - (set (match_operand:SI 0 "nonimmediate_operand" "=r,rm") - (plus:SI (match_dup 1) (match_dup 2)))] + (set (match_operand:SWI48 0 "nonimmediate_operand" "=r,rm") + (plus:SWI48 (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (PLUS, SImode, operands) + && ix86_binary_operator_ok (PLUS, mode, operands) /* Current assemblers are broken and do not allow @GOTOFF in ought but a memory context. */ && ! pic_symbolic_operand (operands[2], VOIDmode)" @@ -6948,30 +6564,35 @@ case TYPE_INCDEC: gcc_assert (rtx_equal_p (operands[0], operands[1])); if (operands[2] == const1_rtx) - return "inc{l}\t%0"; + return "inc{}\t%0"; else { gcc_assert (operands[2] == constm1_rtx); - return "dec{l}\t%0"; + return "dec{}\t%0"; } default: gcc_assert (rtx_equal_p (operands[0], operands[1])); - /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. + /* ???? In DImode, we ought to handle there the 32bit case too + - do we need new constraint? */ + /* Make things pretty and `subl $4,%eax' rather than `addl $-4,%eax'. Exceptions: -128 encodes smaller than 128, so swap sign and op. */ if (CONST_INT_P (operands[2]) + /* Avoid overflows. */ + && (mode != DImode + || ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))) && (INTVAL (operands[2]) == 128 || (INTVAL (operands[2]) < 0 && INTVAL (operands[2]) != -128))) { operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{l}\t{%2, %0|%0, %2}"; + return "sub{}\t{%2, %0|%0, %2}"; } - return "add{l}\t{%2, %0|%0, %2}"; + return "add{}\t{%2, %0|%0, %2}"; } } [(set (attr "type") - (if_then_else (match_operand:SI 2 "incdec_operand" "") + (if_then_else (match_operand:SWI48 2 "incdec_operand" "") (const_string "incdec") (const_string "alu"))) (set (attr "length_immediate") @@ -6979,7 +6600,7 @@ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) (const_string "1") (const_string "*"))) - (set_attr "mode" "SI")]) + (set_attr "mode" "")]) ;; See comment for addsi_1_zext why we do use nonimmediate_operand (define_insn "*addsi_2_zext" @@ -7008,7 +6629,7 @@ } default: - /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. + /* Make things pretty and `subl $4,%eax' rather than `addl $-4,%eax'. Exceptions: -128 encodes smaller than 128, so swap sign and op. */ if (CONST_INT_P (operands[2]) && (INTVAL (operands[2]) == 128 @@ -7032,46 +6653,44 @@ (const_string "*"))) (set_attr "mode" "SI")]) -(define_insn "*addsi_3" +(define_insn "*addhi_2" [(set (reg FLAGS_REG) - (compare (neg:SI (match_operand:SI 2 "general_operand" "g")) - (match_operand:SI 1 "nonimmediate_operand" "%0"))) - (clobber (match_scratch:SI 0 "=r"))] - "ix86_match_ccmode (insn, CCZmode) - && !(MEM_P (operands[1]) && MEM_P (operands[2])) - /* Current assemblers are broken and do not allow @GOTOFF in - ought but a memory context. */ - && ! pic_symbolic_operand (operands[2], VOIDmode)" + (compare + (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") + (match_operand:HI 2 "general_operand" "rmn,rn")) + (const_int 0))) + (set (match_operand:HI 0 "nonimmediate_operand" "=r,rm") + (plus:HI (match_dup 1) (match_dup 2)))] + "ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (PLUS, HImode, operands)" { switch (get_attr_type (insn)) { case TYPE_INCDEC: - gcc_assert (rtx_equal_p (operands[0], operands[1])); if (operands[2] == const1_rtx) - return "inc{l}\t%0"; + return "inc{w}\t%0"; else { gcc_assert (operands[2] == constm1_rtx); - return "dec{l}\t%0"; + return "dec{w}\t%0"; } default: - gcc_assert (rtx_equal_p (operands[0], operands[1])); - /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. + /* Make things pretty and `subw $4,%ax' rather than `addw $-4,%ax'. Exceptions: -128 encodes smaller than 128, so swap sign and op. */ if (CONST_INT_P (operands[2]) && (INTVAL (operands[2]) == 128 || (INTVAL (operands[2]) < 0 && INTVAL (operands[2]) != -128))) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{l}\t{%2, %0|%0, %2}"; - } - return "add{l}\t{%2, %0|%0, %2}"; + { + operands[2] = GEN_INT (-INTVAL (operands[2])); + return "sub{w}\t{%2, %0|%0, %2}"; + } + return "add{w}\t{%2, %0|%0, %2}"; } } [(set (attr "type") - (if_then_else (match_operand:SI 2 "incdec_operand" "") + (if_then_else (match_operand:HI 2 "incdec_operand" "") (const_string "incdec") (const_string "alu"))) (set (attr "length_immediate") @@ -7079,98 +6698,95 @@ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) (const_string "1") (const_string "*"))) - (set_attr "mode" "SI")]) + (set_attr "mode" "HI")]) -;; See comment for addsi_1_zext why we do use nonimmediate_operand -(define_insn "*addsi_3_zext" +(define_insn "*addqi_2" [(set (reg FLAGS_REG) - (compare (neg:SI (match_operand:SI 2 "general_operand" "g")) - (match_operand:SI 1 "nonimmediate_operand" "%0"))) - (set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))] - "TARGET_64BIT && ix86_match_ccmode (insn, CCZmode) - && ix86_binary_operator_ok (PLUS, SImode, operands) - /* Current assemblers are broken and do not allow @GOTOFF in - ought but a memory context. */ - && ! pic_symbolic_operand (operands[2], VOIDmode)" + (compare + (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0") + (match_operand:QI 2 "general_operand" "qmn,qn")) + (const_int 0))) + (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm") + (plus:QI (match_dup 1) (match_dup 2)))] + "ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (PLUS, QImode, operands)" { switch (get_attr_type (insn)) { case TYPE_INCDEC: if (operands[2] == const1_rtx) - return "inc{l}\t%k0"; + return "inc{b}\t%0"; else { - gcc_assert (operands[2] == constm1_rtx); - return "dec{l}\t%k0"; + gcc_assert (operands[2] == constm1_rtx + || (CONST_INT_P (operands[2]) + && INTVAL (operands[2]) == 255)); + return "dec{b}\t%0"; } default: - /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. - Exceptions: -128 encodes smaller than 128, so swap sign and op. */ + /* Make things pretty and `subb $4,%al' rather than `addb $-4,%al'. */ if (CONST_INT_P (operands[2]) - && (INTVAL (operands[2]) == 128 - || (INTVAL (operands[2]) < 0 - && INTVAL (operands[2]) != -128))) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{l}\t{%2, %k0|%k0, %2}"; - } - return "add{l}\t{%2, %k0|%k0, %2}"; + && INTVAL (operands[2]) < 0) + { + operands[2] = GEN_INT (-INTVAL (operands[2])); + return "sub{b}\t{%2, %0|%0, %2}"; + } + return "add{b}\t{%2, %0|%0, %2}"; } } [(set (attr "type") - (if_then_else (match_operand:SI 2 "incdec_operand" "") + (if_then_else (match_operand:QI 2 "incdec_operand" "") (const_string "incdec") (const_string "alu"))) - (set (attr "length_immediate") - (if_then_else - (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) - (const_string "1") - (const_string "*"))) - (set_attr "mode" "SI")]) + (set_attr "mode" "QI")]) -; For comparisons against 1, -1 and 128, we may generate better code -; by converting cmp to add, inc or dec as done by peephole2. This pattern -; is matched then. We can't accept general immediate, because for -; case of overflows, the result is messed up. -; This pattern also don't hold of 0x80000000, since the value overflows -; when negated. -; Also carry flag is reversed compared to cmp, so this conversion is valid -; only for comparisons not depending on it. -(define_insn "*addsi_4" +(define_insn "*add_3" [(set (reg FLAGS_REG) - (compare (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:SI 2 "const_int_operand" "n"))) - (clobber (match_scratch:SI 0 "=rm"))] - "ix86_match_ccmode (insn, CCGCmode) - && (INTVAL (operands[2]) & 0xffffffff) != 0x80000000" + (compare + (neg:SWI48 (match_operand:SWI48 2 "" "")) + (match_operand:SWI48 1 "nonimmediate_operand" "%0"))) + (clobber (match_scratch:SWI48 0 "=r"))] + "ix86_match_ccmode (insn, CCZmode) + && !(MEM_P (operands[1]) && MEM_P (operands[2])) + /* Current assemblers are broken and do not allow @GOTOFF in + ought but a memory context. */ + && ! pic_symbolic_operand (operands[2], VOIDmode)" { switch (get_attr_type (insn)) { case TYPE_INCDEC: - if (operands[2] == constm1_rtx) - return "inc{l}\t%0"; + gcc_assert (rtx_equal_p (operands[0], operands[1])); + if (operands[2] == const1_rtx) + return "inc{}\t%0"; else { - gcc_assert (operands[2] == const1_rtx); - return "dec{l}\t%0"; + gcc_assert (operands[2] == constm1_rtx); + return "dec{}\t%0"; } default: gcc_assert (rtx_equal_p (operands[0], operands[1])); + /* ???? In DImode, we ought to handle there the 32bit case too + - do we need new constraint? */ /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. Exceptions: -128 encodes smaller than 128, so swap sign and op. */ - if ((INTVAL (operands[2]) == -128 - || (INTVAL (operands[2]) > 0 - && INTVAL (operands[2]) != 128))) - return "sub{l}\t{%2, %0|%0, %2}"; - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "add{l}\t{%2, %0|%0, %2}"; + if (CONST_INT_P (operands[2]) + /* Avoid overflows. */ + && (mode != DImode + || ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))) + && (INTVAL (operands[2]) == 128 + || (INTVAL (operands[2]) < 0 + && INTVAL (operands[2]) != -128))) + { + operands[2] = GEN_INT (-INTVAL (operands[2])); + return "sub{}\t{%2, %0|%0, %2}"; + } + return "add{}\t{%2, %0|%0, %2}"; } } [(set (attr "type") - (if_then_else (match_operand:SI 2 "incdec_operand" "") + (if_then_else (match_operand:SWI48 2 "incdec_operand" "") (const_string "incdec") (const_string "alu"))) (set (attr "length_immediate") @@ -7178,17 +6794,18 @@ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) (const_string "1") (const_string "*"))) - (set_attr "mode" "SI")]) + (set_attr "mode" "")]) -(define_insn "*addsi_5" +;; See comment for addsi_1_zext why we do use nonimmediate_operand +(define_insn "*addsi_3_zext" [(set (reg FLAGS_REG) (compare - (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0") - (match_operand:SI 2 "general_operand" "g")) - (const_int 0))) - (clobber (match_scratch:SI 0 "=r"))] - "ix86_match_ccmode (insn, CCGOCmode) - && !(MEM_P (operands[1]) && MEM_P (operands[2])) + (neg:SI (match_operand:SI 2 "general_operand" "g")) + (match_operand:SI 1 "nonimmediate_operand" "%0"))) + (set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))] + "TARGET_64BIT && ix86_match_ccmode (insn, CCZmode) + && ix86_binary_operator_ok (PLUS, SImode, operands) /* Current assemblers are broken and do not allow @GOTOFF in ought but a memory context. */ && ! pic_symbolic_operand (operands[2], VOIDmode)" @@ -7196,18 +6813,16 @@ switch (get_attr_type (insn)) { case TYPE_INCDEC: - gcc_assert (rtx_equal_p (operands[0], operands[1])); if (operands[2] == const1_rtx) - return "inc{l}\t%0"; + return "inc{l}\t%k0"; else { gcc_assert (operands[2] == constm1_rtx); - return "dec{l}\t%0"; + return "dec{l}\t%k0"; } default: - gcc_assert (rtx_equal_p (operands[0], operands[1])); - /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. + /* Make things pretty and `subl $4,%eax' rather than `addl $-4,%eax'. Exceptions: -128 encodes smaller than 128, so swap sign and op. */ if (CONST_INT_P (operands[2]) && (INTVAL (operands[2]) == 128 @@ -7215,9 +6830,9 @@ && INTVAL (operands[2]) != -128))) { operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{l}\t{%2, %0|%0, %2}"; + return "sub{l}\t{%2, %k0|%k0, %2}"; } - return "add{l}\t{%2, %0|%0, %2}"; + return "add{l}\t{%2, %k0|%k0, %2}"; } } [(set (attr "type") @@ -7231,40 +6846,28 @@ (const_string "*"))) (set_attr "mode" "SI")]) -(define_expand "addhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (plus:HI (match_operand:HI 1 "nonimmediate_operand" "") - (match_operand:HI 2 "general_operand" "")))] - "TARGET_HIMODE_MATH" - "ix86_expand_binary_operator (PLUS, HImode, operands); DONE;") - -;; %%% After Dave's SUBREG_BYTE stuff goes in, re-enable incb %ah -;; type optimizations enabled by define-splits. This is not important -;; for PII, and in fact harmful because of partial register stalls. - -(define_insn "*addhi_1_lea" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,r") - (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,r") - (match_operand:HI 2 "general_operand" "rn,rm,ln"))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_PARTIAL_REG_STALL - && ix86_binary_operator_ok (PLUS, HImode, operands)" +(define_insn "*addhi_3" + [(set (reg FLAGS_REG) + (compare + (neg:HI (match_operand:HI 2 "general_operand" "rmn")) + (match_operand:HI 1 "nonimmediate_operand" "%0"))) + (clobber (match_scratch:HI 0 "=r"))] + "ix86_match_ccmode (insn, CCZmode) + && !(MEM_P (operands[1]) && MEM_P (operands[2]))" { switch (get_attr_type (insn)) { - case TYPE_LEA: - return "#"; case TYPE_INCDEC: if (operands[2] == const1_rtx) return "inc{w}\t%0"; else - { + { gcc_assert (operands[2] == constm1_rtx); return "dec{w}\t%0"; } default: - /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. + /* Make things pretty and `subw $4,%ax' rather than `addw $-4,%ax'. Exceptions: -128 encodes smaller than 128, so swap sign and op. */ if (CONST_INT_P (operands[2]) && (INTVAL (operands[2]) == 128 @@ -7278,100 +6881,100 @@ } } [(set (attr "type") - (if_then_else (eq_attr "alternative" "2") - (const_string "lea") - (if_then_else (match_operand:HI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu")))) + (if_then_else (match_operand:HI 2 "incdec_operand" "") + (const_string "incdec") + (const_string "alu"))) (set (attr "length_immediate") (if_then_else (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) (const_string "1") (const_string "*"))) - (set_attr "mode" "HI,HI,SI")]) + (set_attr "mode" "HI")]) -(define_insn "*addhi_1" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") - (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") - (match_operand:HI 2 "general_operand" "rn,rm"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_PARTIAL_REG_STALL - && ix86_binary_operator_ok (PLUS, HImode, operands)" +(define_insn "*addqi_3" + [(set (reg FLAGS_REG) + (compare + (neg:QI (match_operand:QI 2 "general_operand" "qmn")) + (match_operand:QI 1 "nonimmediate_operand" "%0"))) + (clobber (match_scratch:QI 0 "=q"))] + "ix86_match_ccmode (insn, CCZmode) + && !(MEM_P (operands[1]) && MEM_P (operands[2]))" { switch (get_attr_type (insn)) { case TYPE_INCDEC: if (operands[2] == const1_rtx) - return "inc{w}\t%0"; + return "inc{b}\t%0"; else { - gcc_assert (operands[2] == constm1_rtx); - return "dec{w}\t%0"; + gcc_assert (operands[2] == constm1_rtx + || (CONST_INT_P (operands[2]) + && INTVAL (operands[2]) == 255)); + return "dec{b}\t%0"; } default: - /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. - Exceptions: -128 encodes smaller than 128, so swap sign and op. */ + /* Make things pretty and `subb $4,%al' rather than `addb $-4,%al'. */ if (CONST_INT_P (operands[2]) - && (INTVAL (operands[2]) == 128 - || (INTVAL (operands[2]) < 0 - && INTVAL (operands[2]) != -128))) + && INTVAL (operands[2]) < 0) { operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{w}\t{%2, %0|%0, %2}"; + return "sub{b}\t{%2, %0|%0, %2}"; } - return "add{w}\t{%2, %0|%0, %2}"; + return "add{b}\t{%2, %0|%0, %2}"; } } [(set (attr "type") - (if_then_else (match_operand:HI 2 "incdec_operand" "") + (if_then_else (match_operand:QI 2 "incdec_operand" "") (const_string "incdec") (const_string "alu"))) - (set (attr "length_immediate") - (if_then_else - (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) - (const_string "1") - (const_string "*"))) - (set_attr "mode" "HI")]) + (set_attr "mode" "QI")]) -(define_insn "*addhi_2" +; For comparisons against 1, -1 and 128, we may generate better code +; by converting cmp to add, inc or dec as done by peephole2. This pattern +; is matched then. We can't accept general immediate, because for +; case of overflows, the result is messed up. +; This pattern also don't hold of 0x8000000000000000, since the value +; overflows when negated. +; Also carry flag is reversed compared to cmp, so this conversion is valid +; only for comparisons not depending on it. + +(define_insn "*adddi_4" [(set (reg FLAGS_REG) (compare - (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") - (match_operand:HI 2 "general_operand" "rmn,rn")) - (const_int 0))) - (set (match_operand:HI 0 "nonimmediate_operand" "=r,rm") - (plus:HI (match_dup 1) (match_dup 2)))] - "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (PLUS, HImode, operands)" + (match_operand:DI 1 "nonimmediate_operand" "0") + (match_operand:DI 2 "x86_64_immediate_operand" "e"))) + (clobber (match_scratch:DI 0 "=rm"))] + "TARGET_64BIT + && ix86_match_ccmode (insn, CCGCmode)" { switch (get_attr_type (insn)) { case TYPE_INCDEC: - if (operands[2] == const1_rtx) - return "inc{w}\t%0"; + if (operands[2] == constm1_rtx) + return "inc{q}\t%0"; else { - gcc_assert (operands[2] == constm1_rtx); - return "dec{w}\t%0"; + gcc_assert (operands[2] == const1_rtx); + return "dec{q}\t%0"; } default: - /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. + gcc_assert (rtx_equal_p (operands[0], operands[1])); + /* Make things pretty and `subl $4,%eax' rather than `addl $-4,%eax'. Exceptions: -128 encodes smaller than 128, so swap sign and op. */ - if (CONST_INT_P (operands[2]) - && (INTVAL (operands[2]) == 128 - || (INTVAL (operands[2]) < 0 - && INTVAL (operands[2]) != -128))) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{w}\t{%2, %0|%0, %2}"; - } - return "add{w}\t{%2, %0|%0, %2}"; + if ((INTVAL (operands[2]) == -128 + || (INTVAL (operands[2]) > 0 + && INTVAL (operands[2]) != 128)) + /* Avoid overflows. */ + && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))) + return "sub{q}\t{%2, %0|%0, %2}"; + operands[2] = GEN_INT (-INTVAL (operands[2])); + return "add{q}\t{%2, %0|%0, %2}"; } } [(set (attr "type") - (if_then_else (match_operand:HI 2 "incdec_operand" "") + (if_then_else (match_operand:DI 2 "incdec_operand" "") (const_string "incdec") (const_string "alu"))) (set (attr "length_immediate") @@ -7379,43 +6982,51 @@ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) (const_string "1") (const_string "*"))) - (set_attr "mode" "HI")]) + (set_attr "mode" "DI")]) -(define_insn "*addhi_3" +; For comparisons against 1, -1 and 128, we may generate better code +; by converting cmp to add, inc or dec as done by peephole2. This pattern +; is matched then. We can't accept general immediate, because for +; case of overflows, the result is messed up. +; This pattern also don't hold of 0x80000000, since the value overflows +; when negated. +; Also carry flag is reversed compared to cmp, so this conversion is valid +; only for comparisons not depending on it. + +(define_insn "*addsi_4" [(set (reg FLAGS_REG) - (compare (neg:HI (match_operand:HI 2 "general_operand" "rmn")) - (match_operand:HI 1 "nonimmediate_operand" "%0"))) - (clobber (match_scratch:HI 0 "=r"))] - "ix86_match_ccmode (insn, CCZmode) - && !(MEM_P (operands[1]) && MEM_P (operands[2]))" + (compare + (match_operand:SI 1 "nonimmediate_operand" "0") + (match_operand:SI 2 "const_int_operand" "n"))) + (clobber (match_scratch:SI 0 "=rm"))] + "ix86_match_ccmode (insn, CCGCmode) + && (INTVAL (operands[2]) & 0xffffffff) != 0x80000000" { switch (get_attr_type (insn)) { case TYPE_INCDEC: - if (operands[2] == const1_rtx) - return "inc{w}\t%0"; + if (operands[2] == constm1_rtx) + return "inc{l}\t%0"; else { - gcc_assert (operands[2] == constm1_rtx); - return "dec{w}\t%0"; + gcc_assert (operands[2] == const1_rtx); + return "dec{l}\t%0"; } default: - /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. + gcc_assert (rtx_equal_p (operands[0], operands[1])); + /* Make things pretty and `subl $4,%eax' rather than `addl $-4,%eax'. Exceptions: -128 encodes smaller than 128, so swap sign and op. */ - if (CONST_INT_P (operands[2]) - && (INTVAL (operands[2]) == 128 - || (INTVAL (operands[2]) < 0 - && INTVAL (operands[2]) != -128))) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{w}\t{%2, %0|%0, %2}"; - } - return "add{w}\t{%2, %0|%0, %2}"; + if ((INTVAL (operands[2]) == -128 + || (INTVAL (operands[2]) > 0 + && INTVAL (operands[2]) != 128))) + return "sub{l}\t{%2, %0|%0, %2}"; + operands[2] = GEN_INT (-INTVAL (operands[2])); + return "add{l}\t{%2, %0|%0, %2}"; } } [(set (attr "type") - (if_then_else (match_operand:HI 2 "incdec_operand" "") + (if_then_else (match_operand:SI 2 "incdec_operand" "") (const_string "incdec") (const_string "alu"))) (set (attr "length_immediate") @@ -7423,13 +7034,15 @@ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) (const_string "1") (const_string "*"))) - (set_attr "mode" "HI")]) + (set_attr "mode" "SI")]) ; See comments above addsi_4 for details. + (define_insn "*addhi_4" [(set (reg FLAGS_REG) - (compare (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:HI 2 "const_int_operand" "n"))) + (compare + (match_operand:HI 1 "nonimmediate_operand" "0") + (match_operand:HI 2 "const_int_operand" "n"))) (clobber (match_scratch:HI 0 "=rm"))] "ix86_match_ccmode (insn, CCGCmode) && (INTVAL (operands[2]) & 0xffff) != 0x8000" @@ -7447,7 +7060,7 @@ default: gcc_assert (rtx_equal_p (operands[0], operands[1])); - /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. + /* Make things pretty and `subw $4,%ax' rather than `addw $-4,%ax'. Exceptions: -128 encodes smaller than 128, so swap sign and op. */ if ((INTVAL (operands[2]) == -128 || (INTVAL (operands[2]) > 0 @@ -7468,158 +7081,92 @@ (const_string "*"))) (set_attr "mode" "HI")]) +; See comments above addsi_4 for details. -(define_insn "*addhi_5" +(define_insn "*addqi_4" [(set (reg FLAGS_REG) (compare - (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0") - (match_operand:HI 2 "general_operand" "rmn")) - (const_int 0))) - (clobber (match_scratch:HI 0 "=r"))] - "ix86_match_ccmode (insn, CCGOCmode) - && !(MEM_P (operands[1]) && MEM_P (operands[2]))" + (match_operand:QI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const_int_operand" "n"))) + (clobber (match_scratch:QI 0 "=qm"))] + "ix86_match_ccmode (insn, CCGCmode) + && (INTVAL (operands[2]) & 0xff) != 0x80" { switch (get_attr_type (insn)) { case TYPE_INCDEC: - if (operands[2] == const1_rtx) - return "inc{w}\t%0"; + if (operands[2] == constm1_rtx + || (CONST_INT_P (operands[2]) + && INTVAL (operands[2]) == 255)) + return "inc{b}\t%0"; else { - gcc_assert (operands[2] == constm1_rtx); - return "dec{w}\t%0"; + gcc_assert (operands[2] == const1_rtx); + return "dec{b}\t%0"; } default: - /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. - Exceptions: -128 encodes smaller than 128, so swap sign and op. */ - if (CONST_INT_P (operands[2]) - && (INTVAL (operands[2]) == 128 - || (INTVAL (operands[2]) < 0 - && INTVAL (operands[2]) != -128))) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{w}\t{%2, %0|%0, %2}"; - } - return "add{w}\t{%2, %0|%0, %2}"; + gcc_assert (rtx_equal_p (operands[0], operands[1])); + if (INTVAL (operands[2]) < 0) + { + operands[2] = GEN_INT (-INTVAL (operands[2])); + return "add{b}\t{%2, %0|%0, %2}"; + } + return "sub{b}\t{%2, %0|%0, %2}"; } } [(set (attr "type") (if_then_else (match_operand:HI 2 "incdec_operand" "") (const_string "incdec") (const_string "alu"))) - (set (attr "length_immediate") - (if_then_else - (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) - (const_string "1") - (const_string "*"))) - (set_attr "mode" "HI")]) - -(define_expand "addqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (plus:QI (match_operand:QI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "general_operand" "")))] - "TARGET_QIMODE_MATH" - "ix86_expand_binary_operator (PLUS, QImode, operands); DONE;") - -;; %%% Potential partial reg stall on alternative 2. What to do? -(define_insn "*addqi_1_lea" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r,r") - (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0,r") - (match_operand:QI 2 "general_operand" "qn,qmn,rn,ln"))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_PARTIAL_REG_STALL - && ix86_binary_operator_ok (PLUS, QImode, operands)" -{ - int widen = (which_alternative == 2); - switch (get_attr_type (insn)) - { - case TYPE_LEA: - return "#"; - case TYPE_INCDEC: - if (operands[2] == const1_rtx) - return widen ? "inc{l}\t%k0" : "inc{b}\t%0"; - else - { - gcc_assert (operands[2] == constm1_rtx); - return widen ? "dec{l}\t%k0" : "dec{b}\t%0"; - } - - default: - /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. - Exceptions: -128 encodes smaller than 128, so swap sign and op. */ - if (CONST_INT_P (operands[2]) - && (INTVAL (operands[2]) == 128 - || (INTVAL (operands[2]) < 0 - && INTVAL (operands[2]) != -128))) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - if (widen) - return "sub{l}\t{%2, %k0|%k0, %2}"; - else - return "sub{b}\t{%2, %0|%0, %2}"; - } - if (widen) - return "add{l}\t{%k2, %k0|%k0, %k2}"; - else - return "add{b}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (if_then_else (eq_attr "alternative" "3") - (const_string "lea") - (if_then_else (match_operand:QI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu")))) - (set (attr "length_immediate") - (if_then_else - (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) - (const_string "1") - (const_string "*"))) - (set_attr "mode" "QI,QI,SI,SI")]) + (set_attr "mode" "QI")]) -(define_insn "*addqi_1" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r") - (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0") - (match_operand:QI 2 "general_operand" "qn,qmn,rn"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_PARTIAL_REG_STALL - && ix86_binary_operator_ok (PLUS, QImode, operands)" +(define_insn "*add_5" + [(set (reg FLAGS_REG) + (compare + (plus:SWI48 + (match_operand:SWI48 1 "nonimmediate_operand" "%0") + (match_operand:SWI48 2 "" "")) + (const_int 0))) + (clobber (match_scratch:SWI48 0 "=r"))] + "ix86_match_ccmode (insn, CCGOCmode) + && !(MEM_P (operands[1]) && MEM_P (operands[2])) + /* Current assemblers are broken and do not allow @GOTOFF in + ought but a memory context. */ + && ! pic_symbolic_operand (operands[2], VOIDmode)" { - int widen = (which_alternative == 2); switch (get_attr_type (insn)) { case TYPE_INCDEC: + gcc_assert (rtx_equal_p (operands[0], operands[1])); if (operands[2] == const1_rtx) - return widen ? "inc{l}\t%k0" : "inc{b}\t%0"; + return "inc{}\t%0"; else - { - gcc_assert (operands[2] == constm1_rtx); - return widen ? "dec{l}\t%k0" : "dec{b}\t%0"; + { + gcc_assert (operands[2] == constm1_rtx); + return "dec{}\t%0"; } default: - /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. + gcc_assert (rtx_equal_p (operands[0], operands[1])); + /* Make things pretty and `subl $4,%eax' rather than `addl $-4,%eax'. Exceptions: -128 encodes smaller than 128, so swap sign and op. */ if (CONST_INT_P (operands[2]) + /* Avoid overflows. */ + && (mode != DImode + || ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1)))) && (INTVAL (operands[2]) == 128 || (INTVAL (operands[2]) < 0 && INTVAL (operands[2]) != -128))) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - if (widen) - return "sub{l}\t{%2, %k0|%k0, %2}"; - else - return "sub{b}\t{%2, %0|%0, %2}"; - } - if (widen) - return "add{l}\t{%k2, %k0|%k0, %k2}"; - else - return "add{b}\t{%2, %0|%0, %2}"; + { + operands[2] = GEN_INT (-INTVAL (operands[2])); + return "sub{}\t{%2, %0|%0, %2}"; + } + return "add{}\t{%2, %0|%0, %2}"; } } [(set (attr "type") - (if_then_else (match_operand:QI 2 "incdec_operand" "") + (if_then_else (match_operand:SWI48 2 "incdec_operand" "") (const_string "incdec") (const_string "alu"))) (set (attr "length_immediate") @@ -7627,165 +7174,53 @@ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) (const_string "1") (const_string "*"))) - (set_attr "mode" "QI,QI,SI")]) - -(define_insn "*addqi_1_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) - (plus:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "qn,qnm"))) - (clobber (reg:CC FLAGS_REG))] - "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" -{ - switch (get_attr_type (insn)) - { - case TYPE_INCDEC: - if (operands[1] == const1_rtx) - return "inc{b}\t%0"; - else - { - gcc_assert (operands[1] == constm1_rtx); - return "dec{b}\t%0"; - } - - default: - /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. */ - if (CONST_INT_P (operands[1]) - && INTVAL (operands[1]) < 0) - { - operands[1] = GEN_INT (-INTVAL (operands[1])); - return "sub{b}\t{%1, %0|%0, %1}"; - } - return "add{b}\t{%1, %0|%0, %1}"; - } -} - [(set (attr "type") - (if_then_else (match_operand:QI 1 "incdec_operand" "") - (const_string "incdec") - (const_string "alu1"))) - (set (attr "memory") - (if_then_else (match_operand 1 "memory_operand" "") - (const_string "load") - (const_string "none"))) - (set_attr "mode" "QI")]) + (set_attr "mode" "")]) -(define_insn "*addqi_2" +(define_insn "*addhi_5" [(set (reg FLAGS_REG) (compare - (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0") - (match_operand:QI 2 "general_operand" "qmn,qn")) + (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0") + (match_operand:HI 2 "general_operand" "rmn")) (const_int 0))) - (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm") - (plus:QI (match_dup 1) (match_dup 2)))] + (clobber (match_scratch:HI 0 "=r"))] "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (PLUS, QImode, operands)" -{ - switch (get_attr_type (insn)) - { - case TYPE_INCDEC: - if (operands[2] == const1_rtx) - return "inc{b}\t%0"; - else - { - gcc_assert (operands[2] == constm1_rtx - || (CONST_INT_P (operands[2]) - && INTVAL (operands[2]) == 255)); - return "dec{b}\t%0"; - } - - default: - /* Make things pretty and `subb $4,%al' rather than `addb $-4, %al'. */ - if (CONST_INT_P (operands[2]) - && INTVAL (operands[2]) < 0) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{b}\t{%2, %0|%0, %2}"; - } - return "add{b}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (if_then_else (match_operand:QI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu"))) - (set_attr "mode" "QI")]) - -(define_insn "*addqi_3" - [(set (reg FLAGS_REG) - (compare (neg:QI (match_operand:QI 2 "general_operand" "qmn")) - (match_operand:QI 1 "nonimmediate_operand" "%0"))) - (clobber (match_scratch:QI 0 "=q"))] - "ix86_match_ccmode (insn, CCZmode) && !(MEM_P (operands[1]) && MEM_P (operands[2]))" { switch (get_attr_type (insn)) { case TYPE_INCDEC: - if (operands[2] == const1_rtx) - return "inc{b}\t%0"; - else - { - gcc_assert (operands[2] == constm1_rtx - || (CONST_INT_P (operands[2]) - && INTVAL (operands[2]) == 255)); - return "dec{b}\t%0"; - } - - default: - /* Make things pretty and `subb $4,%al' rather than `addb $-4, %al'. */ - if (CONST_INT_P (operands[2]) - && INTVAL (operands[2]) < 0) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "sub{b}\t{%2, %0|%0, %2}"; - } - return "add{b}\t{%2, %0|%0, %2}"; - } -} - [(set (attr "type") - (if_then_else (match_operand:QI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu"))) - (set_attr "mode" "QI")]) - -; See comments above addsi_4 for details. -(define_insn "*addqi_4" - [(set (reg FLAGS_REG) - (compare (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_operand" "n"))) - (clobber (match_scratch:QI 0 "=qm"))] - "ix86_match_ccmode (insn, CCGCmode) - && (INTVAL (operands[2]) & 0xff) != 0x80" -{ - switch (get_attr_type (insn)) - { - case TYPE_INCDEC: - if (operands[2] == constm1_rtx - || (CONST_INT_P (operands[2]) - && INTVAL (operands[2]) == 255)) - return "inc{b}\t%0"; + if (operands[2] == const1_rtx) + return "inc{w}\t%0"; else { - gcc_assert (operands[2] == const1_rtx); - return "dec{b}\t%0"; + gcc_assert (operands[2] == constm1_rtx); + return "dec{w}\t%0"; } default: - gcc_assert (rtx_equal_p (operands[0], operands[1])); - if (INTVAL (operands[2]) < 0) - { - operands[2] = GEN_INT (-INTVAL (operands[2])); - return "add{b}\t{%2, %0|%0, %2}"; - } - return "sub{b}\t{%2, %0|%0, %2}"; + /* Make things pretty and `subw $4,%ax' rather than `addw $-4,%ax'. + Exceptions: -128 encodes smaller than 128, so swap sign and op. */ + if (CONST_INT_P (operands[2]) + && (INTVAL (operands[2]) == 128 + || (INTVAL (operands[2]) < 0 + && INTVAL (operands[2]) != -128))) + { + operands[2] = GEN_INT (-INTVAL (operands[2])); + return "sub{w}\t{%2, %0|%0, %2}"; + } + return "add{w}\t{%2, %0|%0, %2}"; } } [(set (attr "type") (if_then_else (match_operand:HI 2 "incdec_operand" "") (const_string "incdec") (const_string "alu"))) - (set_attr "mode" "QI")]) - + (set (attr "length_immediate") + (if_then_else + (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" "")) + (const_string "1") + (const_string "*"))) + (set_attr "mode" "HI")]) (define_insn "*addqi_5" [(set (reg FLAGS_REG) @@ -7811,7 +7246,7 @@ } default: - /* Make things pretty and `subb $4,%al' rather than `addb $-4, %al'. */ + /* Make things pretty and `subb $4,%al' rather than `addb $-4,%al'. */ if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0) { @@ -7827,8 +7262,7 @@ (const_string "alu"))) (set_attr "mode" "QI")]) - -(define_insn "addqi_ext_1" +(define_insn "*addqi_ext_1_rex64" [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") (const_int 8) (const_int 8)) @@ -7837,9 +7271,9 @@ (match_operand 1 "ext_register_operand" "0") (const_int 8) (const_int 8)) - (match_operand:QI 2 "general_operand" "Qmn"))) + (match_operand:QI 2 "nonmemory_operand" "Qn"))) (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT" + "TARGET_64BIT" { switch (get_attr_type (insn)) { @@ -7852,7 +7286,7 @@ || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 255)); return "dec{b}\t%h0"; - } + } default: return "add{b}\t{%2, %h0|%h0, %2}"; @@ -7865,7 +7299,7 @@ (set_attr "modrm" "1") (set_attr "mode" "QI")]) -(define_insn "*addqi_ext_1_rex64" +(define_insn "addqi_ext_1" [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") (const_int 8) (const_int 8)) @@ -7874,9 +7308,9 @@ (match_operand 1 "ext_register_operand" "0") (const_int 8) (const_int 8)) - (match_operand:QI 2 "nonmemory_operand" "Qn"))) + (match_operand:QI 2 "general_operand" "Qmn"))) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT" + "!TARGET_64BIT" { switch (get_attr_type (insn)) { @@ -7889,210 +7323,336 @@ || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 255)); return "dec{b}\t%h0"; - } + } default: return "add{b}\t{%2, %h0|%h0, %2}"; } } - [(set (attr "type") - (if_then_else (match_operand:QI 2 "incdec_operand" "") - (const_string "incdec") - (const_string "alu"))) - (set_attr "modrm" "1") - (set_attr "mode" "QI")]) + [(set (attr "type") + (if_then_else (match_operand:QI 2 "incdec_operand" "") + (const_string "incdec") + (const_string "alu"))) + (set_attr "modrm" "1") + (set_attr "mode" "QI")]) + +(define_insn "*addqi_ext_2" + [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") + (const_int 8) + (const_int 8)) + (plus:SI + (zero_extract:SI + (match_operand 1 "ext_register_operand" "%0") + (const_int 8) + (const_int 8)) + (zero_extract:SI + (match_operand 2 "ext_register_operand" "Q") + (const_int 8) + (const_int 8)))) + (clobber (reg:CC FLAGS_REG))] + "" + "add{b}\t{%h2, %h0|%h0, %h2}" + [(set_attr "type" "alu") + (set_attr "mode" "QI")]) + +(define_insn "*lea_1_rex64" + [(set (match_operand:DI 0 "register_operand" "=r") + (match_operand:DI 1 "no_seg_address_operand" "p"))] + "TARGET_64BIT" + "lea{q}\t{%a1, %0|%0, %a1}" + [(set_attr "type" "lea") + (set_attr "mode" "DI")]) + +(define_insn "*lea_1" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operand:SI 1 "no_seg_address_operand" "p"))] + "!TARGET_64BIT" + "lea{l}\t{%a1, %0|%0, %a1}" + [(set_attr "type" "lea") + (set_attr "mode" "SI")]) + +(define_insn "*lea_1_zext" + [(set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI + (subreg:SI (match_operand:DI 1 "no_seg_address_operand" "p") 0)))] + "TARGET_64BIT" + "lea{l}\t{%a1, %k0|%k0, %a1}" + [(set_attr "type" "lea") + (set_attr "mode" "SI")]) + +(define_insn "*lea_2_rex64" + [(set (match_operand:SI 0 "register_operand" "=r") + (subreg:SI (match_operand:DI 1 "no_seg_address_operand" "p") 0))] + "TARGET_64BIT" + "lea{l}\t{%a1, %0|%0, %a1}" + [(set_attr "type" "lea") + (set_attr "mode" "SI")]) + +;; The lea patterns for non-Pmodes needs to be matched by +;; several insns converted to real lea by splitters. + +(define_insn_and_split "*lea_general_1" + [(set (match_operand 0 "register_operand" "=r") + (plus (plus (match_operand 1 "index_register_operand" "l") + (match_operand 2 "register_operand" "r")) + (match_operand 3 "immediate_operand" "i")))] + "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode + || (TARGET_64BIT && GET_MODE (operands[0]) == SImode)) + && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) + && GET_MODE (operands[0]) == GET_MODE (operands[1]) + && GET_MODE (operands[0]) == GET_MODE (operands[2]) + && (GET_MODE (operands[0]) == GET_MODE (operands[3]) + || GET_MODE (operands[3]) == VOIDmode)" + "#" + "&& reload_completed" + [(const_int 0)] +{ + rtx pat; + operands[0] = gen_lowpart (SImode, operands[0]); + operands[1] = gen_lowpart (Pmode, operands[1]); + operands[2] = gen_lowpart (Pmode, operands[2]); + operands[3] = gen_lowpart (Pmode, operands[3]); + pat = gen_rtx_PLUS (Pmode, gen_rtx_PLUS (Pmode, operands[1], operands[2]), + operands[3]); + if (Pmode != SImode) + pat = gen_rtx_SUBREG (SImode, pat, 0); + emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat)); + DONE; +} + [(set_attr "type" "lea") + (set_attr "mode" "SI")]) + +(define_insn_and_split "*lea_general_1_zext" + [(set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI + (plus:SI (plus:SI + (match_operand:SI 1 "index_register_operand" "l") + (match_operand:SI 2 "register_operand" "r")) + (match_operand:SI 3 "immediate_operand" "i"))))] + "TARGET_64BIT" + "#" + "&& reload_completed" + [(set (match_dup 0) + (zero_extend:DI (subreg:SI (plus:DI (plus:DI (match_dup 1) + (match_dup 2)) + (match_dup 3)) 0)))] +{ + operands[1] = gen_lowpart (Pmode, operands[1]); + operands[2] = gen_lowpart (Pmode, operands[2]); + operands[3] = gen_lowpart (Pmode, operands[3]); +} + [(set_attr "type" "lea") + (set_attr "mode" "SI")]) + +(define_insn_and_split "*lea_general_2" + [(set (match_operand 0 "register_operand" "=r") + (plus (mult (match_operand 1 "index_register_operand" "l") + (match_operand 2 "const248_operand" "i")) + (match_operand 3 "nonmemory_operand" "ri")))] + "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode + || (TARGET_64BIT && GET_MODE (operands[0]) == SImode)) + && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) + && GET_MODE (operands[0]) == GET_MODE (operands[1]) + && (GET_MODE (operands[0]) == GET_MODE (operands[3]) + || GET_MODE (operands[3]) == VOIDmode)" + "#" + "&& reload_completed" + [(const_int 0)] +{ + rtx pat; + operands[0] = gen_lowpart (SImode, operands[0]); + operands[1] = gen_lowpart (Pmode, operands[1]); + operands[3] = gen_lowpart (Pmode, operands[3]); + pat = gen_rtx_PLUS (Pmode, gen_rtx_MULT (Pmode, operands[1], operands[2]), + operands[3]); + if (Pmode != SImode) + pat = gen_rtx_SUBREG (SImode, pat, 0); + emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat)); + DONE; +} + [(set_attr "type" "lea") + (set_attr "mode" "SI")]) + +(define_insn_and_split "*lea_general_2_zext" + [(set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI + (plus:SI (mult:SI + (match_operand:SI 1 "index_register_operand" "l") + (match_operand:SI 2 "const248_operand" "n")) + (match_operand:SI 3 "nonmemory_operand" "ri"))))] + "TARGET_64BIT" + "#" + "&& reload_completed" + [(set (match_dup 0) + (zero_extend:DI (subreg:SI (plus:DI (mult:DI (match_dup 1) + (match_dup 2)) + (match_dup 3)) 0)))] +{ + operands[1] = gen_lowpart (Pmode, operands[1]); + operands[3] = gen_lowpart (Pmode, operands[3]); +} + [(set_attr "type" "lea") + (set_attr "mode" "SI")]) + +(define_insn_and_split "*lea_general_3" + [(set (match_operand 0 "register_operand" "=r") + (plus (plus (mult (match_operand 1 "index_register_operand" "l") + (match_operand 2 "const248_operand" "i")) + (match_operand 3 "register_operand" "r")) + (match_operand 4 "immediate_operand" "i")))] + "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode + || (TARGET_64BIT && GET_MODE (operands[0]) == SImode)) + && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) + && GET_MODE (operands[0]) == GET_MODE (operands[1]) + && GET_MODE (operands[0]) == GET_MODE (operands[3])" + "#" + "&& reload_completed" + [(const_int 0)] +{ + rtx pat; + operands[0] = gen_lowpart (SImode, operands[0]); + operands[1] = gen_lowpart (Pmode, operands[1]); + operands[3] = gen_lowpart (Pmode, operands[3]); + operands[4] = gen_lowpart (Pmode, operands[4]); + pat = gen_rtx_PLUS (Pmode, + gen_rtx_PLUS (Pmode, gen_rtx_MULT (Pmode, operands[1], + operands[2]), + operands[3]), + operands[4]); + if (Pmode != SImode) + pat = gen_rtx_SUBREG (SImode, pat, 0); + emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat)); + DONE; +} + [(set_attr "type" "lea") + (set_attr "mode" "SI")]) + +(define_insn_and_split "*lea_general_3_zext" + [(set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI + (plus:SI (plus:SI + (mult:SI + (match_operand:SI 1 "index_register_operand" "l") + (match_operand:SI 2 "const248_operand" "n")) + (match_operand:SI 3 "register_operand" "r")) + (match_operand:SI 4 "immediate_operand" "i"))))] + "TARGET_64BIT" + "#" + "&& reload_completed" + [(set (match_dup 0) + (zero_extend:DI (subreg:SI (plus:DI (plus:DI (mult:DI (match_dup 1) + (match_dup 2)) + (match_dup 3)) + (match_dup 4)) 0)))] +{ + operands[1] = gen_lowpart (Pmode, operands[1]); + operands[3] = gen_lowpart (Pmode, operands[3]); + operands[4] = gen_lowpart (Pmode, operands[4]); +} + [(set_attr "type" "lea") + (set_attr "mode" "SI")]) -(define_insn "*addqi_ext_2" - [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") - (const_int 8) - (const_int 8)) - (plus:SI - (zero_extract:SI - (match_operand 1 "ext_register_operand" "%0") - (const_int 8) - (const_int 8)) - (zero_extract:SI - (match_operand 2 "ext_register_operand" "Q") - (const_int 8) - (const_int 8)))) +;; Convert lea to the lea pattern to avoid flags dependency. +(define_split + [(set (match_operand:DI 0 "register_operand" "") + (plus:DI (match_operand:DI 1 "register_operand" "") + (match_operand:DI 2 "x86_64_nonmemory_operand" ""))) (clobber (reg:CC FLAGS_REG))] - "" - "add{b}\t{%h2, %h0|%h0, %h2}" - [(set_attr "type" "alu") - (set_attr "mode" "QI")]) - -;; The patterns that match these are at the end of this file. - -(define_expand "addxf3" - [(set (match_operand:XF 0 "register_operand" "") - (plus:XF (match_operand:XF 1 "register_operand" "") - (match_operand:XF 2 "register_operand" "")))] - "TARGET_80387" - "") - -(define_expand "add3" - [(set (match_operand:MODEF 0 "register_operand" "") - (plus:MODEF (match_operand:MODEF 1 "register_operand" "") - (match_operand:MODEF 2 "nonimmediate_operand" "")))] - "(TARGET_80387 && X87_ENABLE_ARITH (mode)) - || (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)" + "TARGET_64BIT && reload_completed + && ix86_lea_for_add_ok (PLUS, insn, operands)" + [(set (match_dup 0) + (plus:DI (match_dup 1) + (match_dup 2)))] "") - -;; Subtract instructions - -;; %%% splits for subditi3 - -(define_expand "subti3" - [(set (match_operand:TI 0 "nonimmediate_operand" "") - (minus:TI (match_operand:TI 1 "nonimmediate_operand" "") - (match_operand:TI 2 "x86_64_general_operand" "")))] - "TARGET_64BIT" - "ix86_expand_binary_operator (MINUS, TImode, operands); DONE;") -(define_insn "*subti3_1" - [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o") - (minus:TI (match_operand:TI 1 "nonimmediate_operand" "0,0") - (match_operand:TI 2 "x86_64_general_operand" "roe,re"))) +;; Convert lea to the lea pattern to avoid flags dependency. +(define_split + [(set (match_operand 0 "register_operand" "") + (plus (match_operand 1 "register_operand" "") + (match_operand 2 "nonmemory_operand" ""))) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (MINUS, TImode, operands)" - "#") + "reload_completed && ix86_lea_for_add_ok (PLUS, insn, operands)" + [(const_int 0)] +{ + rtx pat; + /* In -fPIC mode the constructs like (const (unspec [symbol_ref])) + may confuse gen_lowpart. */ + if (GET_MODE (operands[0]) != Pmode) + { + operands[1] = gen_lowpart (Pmode, operands[1]); + operands[2] = gen_lowpart (Pmode, operands[2]); + } + operands[0] = gen_lowpart (SImode, operands[0]); + pat = gen_rtx_PLUS (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; +}) +;; Convert lea to the lea pattern to avoid flags dependency. (define_split - [(set (match_operand:TI 0 "nonimmediate_operand" "") - (minus:TI (match_operand:TI 1 "nonimmediate_operand" "") - (match_operand:TI 2 "x86_64_general_operand" ""))) + [(set (match_operand:DI 0 "register_operand" "") + (zero_extend:DI + (plus:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "nonmemory_operand" "")))) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && reload_completed" - [(parallel [(set (reg:CC FLAGS_REG) (compare:CC (match_dup 1) (match_dup 2))) - (set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2)))]) - (parallel [(set (match_dup 3) - (minus:DI (match_dup 4) - (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0)) - (match_dup 5)))) - (clobber (reg:CC FLAGS_REG))])] - "split_ti (&operands[0], 3, &operands[0], &operands[3]);") - -;; %%% splits for subsidi3 + "TARGET_64BIT && reload_completed + && true_regnum (operands[0]) != true_regnum (operands[1])" + [(set (match_dup 0) + (zero_extend:DI (subreg:SI (plus:DI (match_dup 1) (match_dup 2)) 0)))] +{ + operands[1] = gen_lowpart (Pmode, operands[1]); + operands[2] = gen_lowpart (Pmode, operands[2]); +}) + +;; Subtract instructions -(define_expand "subdi3" - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (minus:DI (match_operand:DI 1 "nonimmediate_operand" "") - (match_operand:DI 2 "x86_64_general_operand" "")))] +(define_expand "sub3" + [(set (match_operand:SDWI 0 "nonimmediate_operand" "") + (minus:SDWI (match_operand:SDWI 1 "nonimmediate_operand" "") + (match_operand:SDWI 2 "" "")))] "" - "ix86_expand_binary_operator (MINUS, DImode, operands); DONE;") - -(define_insn "*subdi3_1" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o") - (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0") - (match_operand:DI 2 "general_operand" "roiF,riF"))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)" - "#") + "ix86_expand_binary_operator (MINUS, mode, operands); DONE;") -(define_split - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (minus:DI (match_operand:DI 1 "nonimmediate_operand" "") - (match_operand:DI 2 "general_operand" ""))) +(define_insn_and_split "*sub3_doubleword" + [(set (match_operand:DWI 0 "nonimmediate_operand" "=r,o") + (minus:DWI + (match_operand:DWI 1 "nonimmediate_operand" "0,0") + (match_operand:DWI 2 "" "ro,r"))) (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT && reload_completed" - [(parallel [(set (reg:CC FLAGS_REG) (compare:CC (match_dup 1) (match_dup 2))) - (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))]) + "ix86_binary_operator_ok (MINUS, mode, operands)" + "#" + "reload_completed" + [(parallel [(set (reg:CC FLAGS_REG) + (compare:CC (match_dup 1) (match_dup 2))) + (set (match_dup 0) + (minus: (match_dup 1) (match_dup 2)))]) (parallel [(set (match_dup 3) - (minus:SI (match_dup 4) - (plus:SI (ltu:SI (reg:CC FLAGS_REG) (const_int 0)) - (match_dup 5)))) + (minus: + (match_dup 4) + (plus: + (ltu: (reg:CC FLAGS_REG) (const_int 0)) + (match_dup 5)))) (clobber (reg:CC FLAGS_REG))])] - "split_di (&operands[0], 3, &operands[0], &operands[3]);") - -(define_insn "subdi3_carry_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r") - (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0") - (plus:DI (match_operand:DI 3 "ix86_carry_flag_operator" "") - (match_operand:DI 2 "x86_64_general_operand" "re,rm")))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)" - "sbb{q}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "mode" "DI")]) - -(define_insn "*subdi_1_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r") - (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0") - (match_operand:DI 2 "x86_64_general_operand" "re,rm"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)" - "sub{q}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "DI")]) - -(define_insn "*subdi_2_rex64" - [(set (reg FLAGS_REG) - (compare - (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0") - (match_operand:DI 2 "x86_64_general_operand" "re,rm")) - (const_int 0))) - (set (match_operand:DI 0 "nonimmediate_operand" "=rm,r") - (minus:DI (match_dup 1) (match_dup 2)))] - "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (MINUS, DImode, operands)" - "sub{q}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "DI")]) - -(define_insn "*subdi_3_rex63" - [(set (reg FLAGS_REG) - (compare (match_operand:DI 1 "nonimmediate_operand" "0,0") - (match_operand:DI 2 "x86_64_general_operand" "re,rm"))) - (set (match_operand:DI 0 "nonimmediate_operand" "=rm,r") - (minus:DI (match_dup 1) (match_dup 2)))] - "TARGET_64BIT && ix86_match_ccmode (insn, CCmode) - && ix86_binary_operator_ok (MINUS, SImode, operands)" - "sub{q}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "DI")]) - -(define_insn "subqi3_carry" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q") - (minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") - (plus:QI (match_operand:QI 3 "ix86_carry_flag_operator" "") - (match_operand:QI 2 "general_operand" "qn,qm")))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (MINUS, QImode, operands)" - "sbb{b}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "mode" "QI")]) - -(define_insn "subhi3_carry" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") - (minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0") - (plus:HI (match_operand:HI 3 "ix86_carry_flag_operator" "") - (match_operand:HI 2 "general_operand" "rn,rm")))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (MINUS, HImode, operands)" - "sbb{w}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "mode" "HI")]) - -(define_insn "subsi3_carry" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") - (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0") - (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "") - (match_operand:SI 2 "general_operand" "ri,rm")))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (MINUS, SImode, operands)" - "sbb{l}\t{%2, %0|%0, %2}" + "split_ (&operands[0], 3, &operands[0], &operands[3]);") + +(define_insn "sub3_carry" + [(set (match_operand:SWI 0 "nonimmediate_operand" "=m,") + (minus:SWI + (match_operand:SWI 1 "nonimmediate_operand" "0,0") + (plus:SWI + (match_operand:SWI 3 "ix86_carry_flag_operator" "") + (match_operand:SWI 2 "" ",m")))) + (clobber (reg:CC FLAGS_REG))] + "ix86_binary_operator_ok (MINUS, mode, operands)" + "sbb{}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") (set_attr "use_carry" "1") (set_attr "pent_pair" "pu") - (set_attr "mode" "SI")]) + (set_attr "mode" "")]) -(define_insn "subsi3_carry_zext" +(define_insn "*subsi3_carry_zext" [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI (minus:SI (match_operand:SI 1 "register_operand" "0") @@ -8105,22 +7665,28 @@ (set_attr "pent_pair" "pu") (set_attr "mode" "SI")]) -(define_expand "subsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (minus:SI (match_operand:SI 1 "nonimmediate_operand" "") - (match_operand:SI 2 "general_operand" "")))] +(define_insn "*sub3_cconly_overflow" + [(set (reg:CCC FLAGS_REG) + (compare:CCC + (minus:SWI + (match_operand:SWI 0 "nonimmediate_operand" "m,") + (match_operand:SWI 1 "" ",m")) + (match_dup 0)))] "" - "ix86_expand_binary_operator (MINUS, SImode, operands); DONE;") + "cmp{}\t{%1, %0|%0, %1}" + [(set_attr "type" "icmp") + (set_attr "mode" "")]) -(define_insn "*subsi_1" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") - (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0") - (match_operand:SI 2 "general_operand" "ri,rm"))) +(define_insn "*sub_1" + [(set (match_operand:SWI 0 "nonimmediate_operand" "=m,") + (minus:SWI + (match_operand:SWI 1 "nonimmediate_operand" "0,0") + (match_operand:SWI 2 "" ",m"))) (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (MINUS, SImode, operands)" - "sub{l}\t{%2, %0|%0, %2}" + "ix86_binary_operator_ok (MINUS, mode, operands)" + "sub{}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") - (set_attr "mode" "SI")]) + (set_attr "mode" "")]) (define_insn "*subsi_1_zext" [(set (match_operand:DI 0 "register_operand" "=r") @@ -8133,19 +7699,31 @@ [(set_attr "type" "alu") (set_attr "mode" "SI")]) -(define_insn "*subsi_2" +(define_insn "*subqi_1_slp" + [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) + (minus:QI (match_dup 0) + (match_operand:QI 1 "general_operand" "qn,qm"))) + (clobber (reg:CC FLAGS_REG))] + "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) + && !(MEM_P (operands[0]) && MEM_P (operands[1]))" + "sub{b}\t{%1, %0|%0, %1}" + [(set_attr "type" "alu1") + (set_attr "mode" "QI")]) + +(define_insn "*sub_2" [(set (reg FLAGS_REG) (compare - (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0") - (match_operand:SI 2 "general_operand" "ri,rm")) + (minus:SWI + (match_operand:SWI 1 "nonimmediate_operand" "0,0") + (match_operand:SWI 2 "" ",m")) (const_int 0))) - (set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") - (minus:SI (match_dup 1) (match_dup 2)))] + (set (match_operand:SWI 0 "nonimmediate_operand" "=m,") + (minus:SWI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (MINUS, SImode, operands)" - "sub{l}\t{%2, %0|%0, %2}" + && ix86_binary_operator_ok (MINUS, mode, operands)" + "sub{}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") - (set_attr "mode" "SI")]) + (set_attr "mode" "")]) (define_insn "*subsi_2_zext" [(set (reg FLAGS_REG) @@ -8163,17 +7741,17 @@ [(set_attr "type" "alu") (set_attr "mode" "SI")]) -(define_insn "*subsi_3" +(define_insn "*sub_3" [(set (reg FLAGS_REG) - (compare (match_operand:SI 1 "nonimmediate_operand" "0,0") - (match_operand:SI 2 "general_operand" "ri,rm"))) - (set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") - (minus:SI (match_dup 1) (match_dup 2)))] + (compare (match_operand:SWI 1 "nonimmediate_operand" "0,0") + (match_operand:SWI 2 "" ",m"))) + (set (match_operand:SWI 0 "nonimmediate_operand" "=m,") + (minus:SWI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCmode) - && ix86_binary_operator_ok (MINUS, SImode, operands)" - "sub{l}\t{%2, %0|%0, %2}" + && ix86_binary_operator_ok (MINUS, mode, operands)" + "sub{}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") - (set_attr "mode" "SI")]) + (set_attr "mode" "")]) (define_insn "*subsi_3_zext" [(set (reg FLAGS_REG) @@ -8187,118 +7765,52 @@ && ix86_binary_operator_ok (MINUS, SImode, operands)" "sub{l}\t{%2, %1|%1, %2}" [(set_attr "type" "alu") - (set_attr "mode" "DI")]) - -(define_expand "subhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (minus:HI (match_operand:HI 1 "nonimmediate_operand" "") - (match_operand:HI 2 "general_operand" "")))] - "TARGET_HIMODE_MATH" - "ix86_expand_binary_operator (MINUS, HImode, operands); DONE;") - -(define_insn "*subhi_1" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") - (minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0") - (match_operand:HI 2 "general_operand" "rn,rm"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (MINUS, HImode, operands)" - "sub{w}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "HI")]) - -(define_insn "*subhi_2" - [(set (reg FLAGS_REG) - (compare - (minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0") - (match_operand:HI 2 "general_operand" "rn,rm")) - (const_int 0))) - (set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") - (minus:HI (match_dup 1) (match_dup 2)))] - "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (MINUS, HImode, operands)" - "sub{w}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "HI")]) - -(define_insn "*subhi_3" - [(set (reg FLAGS_REG) - (compare (match_operand:HI 1 "nonimmediate_operand" "0,0") - (match_operand:HI 2 "general_operand" "rn,rm"))) - (set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") - (minus:HI (match_dup 1) (match_dup 2)))] - "ix86_match_ccmode (insn, CCmode) - && ix86_binary_operator_ok (MINUS, HImode, operands)" - "sub{w}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "HI")]) - -(define_expand "subqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (minus:QI (match_operand:QI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "general_operand" "")))] - "TARGET_QIMODE_MATH" - "ix86_expand_binary_operator (MINUS, QImode, operands); DONE;") - -(define_insn "*subqi_1" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q") - (minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") - (match_operand:QI 2 "general_operand" "qn,qm"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (MINUS, QImode, operands)" - "sub{b}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "QI")]) + (set_attr "mode" "SI")]) -(define_insn "*subqi_1_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) - (minus:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "qn,qm"))) - (clobber (reg:CC FLAGS_REG))] - "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "sub{b}\t{%1, %0|%0, %1}" - [(set_attr "type" "alu1") - (set_attr "mode" "QI")]) -(define_insn "*subqi_2" - [(set (reg FLAGS_REG) - (compare - (minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") - (match_operand:QI 2 "general_operand" "qn,qm")) - (const_int 0))) - (set (match_operand:QI 0 "nonimmediate_operand" "=qm,q") - (minus:QI (match_dup 1) (match_dup 2)))] - "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (MINUS, QImode, operands)" - "sub{b}\t{%2, %0|%0, %2}" +(define_insn "*3_cc_overflow" + [(set (reg:CCC FLAGS_REG) + (compare:CCC + (plusminus:SWI + (match_operand:SWI 1 "nonimmediate_operand" "0,0") + (match_operand:SWI 2 "" ",m")) + (match_dup 1))) + (set (match_operand:SWI 0 "nonimmediate_operand" "=m,") + (plusminus:SWI (match_dup 1) (match_dup 2)))] + "ix86_binary_operator_ok (, mode, operands)" + "{}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") - (set_attr "mode" "QI")]) + (set_attr "mode" "")]) -(define_insn "*subqi_3" - [(set (reg FLAGS_REG) - (compare (match_operand:QI 1 "nonimmediate_operand" "0,0") - (match_operand:QI 2 "general_operand" "qn,qm"))) - (set (match_operand:QI 0 "nonimmediate_operand" "=qm,q") - (minus:QI (match_dup 1) (match_dup 2)))] - "ix86_match_ccmode (insn, CCmode) - && ix86_binary_operator_ok (MINUS, QImode, operands)" - "sub{b}\t{%2, %0|%0, %2}" +(define_insn "*si3_zext_cc_overflow" + [(set (reg:CCC FLAGS_REG) + (compare:CCC + (plusminus:SI + (match_operand:SI 1 "nonimmediate_operand" "0") + (match_operand:SI 2 "general_operand" "g")) + (match_dup 1))) + (set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI (plusminus:SI (match_dup 1) (match_dup 2))))] + "TARGET_64BIT && ix86_binary_operator_ok (, SImode, operands)" + "{l}\t{%2, %k0|%k0, %2}" [(set_attr "type" "alu") - (set_attr "mode" "QI")]) + (set_attr "mode" "SI")]) ;; The patterns that match these are at the end of this file. -(define_expand "subxf3" +(define_expand "xf3" [(set (match_operand:XF 0 "register_operand" "") - (minus:XF (match_operand:XF 1 "register_operand" "") - (match_operand:XF 2 "register_operand" "")))] + (plusminus:XF + (match_operand:XF 1 "register_operand" "") + (match_operand:XF 2 "register_operand" "")))] "TARGET_80387" "") -(define_expand "sub3" +(define_expand "3" [(set (match_operand:MODEF 0 "register_operand" "") - (minus:MODEF (match_operand:MODEF 1 "register_operand" "") - (match_operand:MODEF 2 "nonimmediate_operand" "")))] + (plusminus:MODEF + (match_operand:MODEF 1 "register_operand" "") + (match_operand:MODEF 2 "nonimmediate_operand" "")))] "(TARGET_80387 && X87_ENABLE_ARITH (mode)) || (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)" "")