diff options
author | Jan Hubicka <jh@suse.cz> | 2000-07-30 18:59:56 +0000 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2000-07-30 18:59:56 +0000 |
commit | 587870645c87fd2c898c6ef9e4048f04cadbf79f (patch) | |
tree | 5c77df3c7f1a3b16186f59f8a8bf96e45a6bca95 | |
parent | 8acb2f2414c3026135f0d6f3e3ce91822c3c8459 (diff) | |
download | gcc-587870645c87fd2c898c6ef9e4048f04cadbf79f.zip gcc-587870645c87fd2c898c6ef9e4048f04cadbf79f.tar.gz gcc-587870645c87fd2c898c6ef9e4048f04cadbf79f.tar.bz2 |
* i386.md (*lea_general_[123]) New insns and splits.
(addsi3 to lea splitter): Handle other modes too.
(shlsi3 to lea splitter): Likewise.
(addhi_1_lea, shlhi_1_lea): New patterns.
(addhi_1, shlhi_1): Conditionize by PARTIAL_REG_STALL.
From-SVN: r35351
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 361 |
2 files changed, 347 insertions, 22 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 80482a3..bbbfc0a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +Sun Jul 30 20:58:34 MET DST 2000 Jan Hubicka <jh@suse.cz> + + * i386.md (*lea_general_[123]) New insns and splits. + (addsi3 to lea splitter): Handle other modes too. + (shlsi3 to lea splitter): Likewise. + (addhi_1_lea, shlhi_1_lea): New patterns. + (addhi_1, shlhi_1): Conditionize by PARTIAL_REG_STALL. + Sun Jul 30 20:51:25 MET DST 2000 Jan Hubicka <jh@suse.cz> * recog.c (general_operand, nonimmediate_operand): Accept diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index a47c6dc..eecb151 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -3740,6 +3740,102 @@ [(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 "register_operand" "r") + (match_operand 2 "register_operand" "r")) + (match_operand 3 "immediate_operand" "i")))] + "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode) + && (!TARGET_PARTIAL_REG_STALL || optimize_size) + && 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_2" + [(set (match_operand 0 "register_operand" "=r") + (plus (mult (match_operand 1 "register_operand" "r") + (match_operand 2 "const248_operand" "i")) + (match_operand 3 "nonmemory_operand" "ri")))] + "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode) + && (!TARGET_PARTIAL_REG_STALL || optimize_size) + && 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_3" + [(set (match_operand 0 "register_operand" "=r") + (plus (plus (mult (match_operand 1 "register_operand" "r") + (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_PARTIAL_REG_STALL || optimize_size) + && 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 "*addsi_1" [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r") (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r") @@ -3796,16 +3892,29 @@ ;; Convert lea to the lea pattern to avoid flags dependency. (define_split - [(set (match_operand:SI 0 "register_operand" "") - (plus:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "nonmemory_operand" ""))) + [(set (match_operand 0 "register_operand" "") + (plus (match_operand 1 "register_operand" "") + (match_operand 2 "nonmemory_operand" ""))) (clobber (reg:CC 17))] - "reload_completed - && true_regnum (operands[0]) != true_regnum (operands[1])" - [(set (match_dup 0) - (plus:SI (match_dup 1) - (match_dup 2)))] - "") + "reload_completed" + [(const_int 0)] + " +{ + rtx pat; + operands[0] = gen_lowpart (SImode, operands[0]); + /* 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]); + } + 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; +}") (define_insn "*addsi_2" [(set (reg 17) @@ -3883,12 +3992,57 @@ ;; 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" "ri,rm,rni"))) + (clobber (reg:CC 17))] + "!TARGET_PARTIAL_REG_STALL + && ix86_binary_operator_ok (PLUS, HImode, operands)" + "* +{ + switch (get_attr_type (insn)) + { + case TYPE_LEA: + return \"#\"; + case TYPE_INCDEC: + if (operands[2] == const1_rtx) + return \"inc{w}\\t%0\"; + else if (operands[2] == constm1_rtx + || (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) == 65535)) + return \"dec{w}\\t%0\"; + abort(); + + 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 (GET_CODE (operands[2]) == CONST_INT + && (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 (eq_attr "alternative" "2") + (const_string "lea") + (if_then_else (match_operand:HI 2 "incdec_operand" "") + (const_string "incdec") + (const_string "alu")))) + (set_attr "mode" "HI,HI,SI")]) + (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" "ri,rm"))) (clobber (reg:CC 17))] - "ix86_binary_operator_ok (PLUS, HImode, operands)" + "TARGET_PARTIAL_REG_STALL + && ix86_binary_operator_ok (PLUS, HImode, operands)" "* { switch (get_attr_type (insn)) @@ -3986,12 +4140,64 @@ "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,rn"))) + (clobber (reg:CC 17))] + "!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 if (operands[2] == constm1_rtx + || (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) == 255)) + return widen ? \"dec{l}\\t%k0\" : \"dec{b}\\t%0\"; + abort(); + + 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 (GET_CODE (operands[2]) == CONST_INT + && (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:HI 2 "incdec_operand" "") + (const_string "incdec") + (const_string "alu")))) + (set_attr "mode" "HI,HI,SI,SI")]) + (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 17))] - "ix86_binary_operator_ok (PLUS, QImode, operands)" + "TARGET_PARTIAL_REG_STALL + && ix86_binary_operator_ok (PLUS, QImode, operands)" "* { int widen = (which_alternative == 2); @@ -6279,16 +6485,24 @@ ;; Convert lea to the lea pattern to avoid flags dependency. (define_split - [(set (match_operand:SI 0 "register_operand" "") - (ashift:SI (match_operand:SI 1 "register_operand" "") - (match_operand:QI 2 "immediate_operand" ""))) + [(set (match_operand 0 "register_operand" "") + (ashift (match_operand 1 "register_operand" "") + (match_operand:QI 2 "const_int_operand" ""))) (clobber (reg:CC 17))] - "reload_completed - && true_regnum (operands[0]) != true_regnum (operands[1])" - [(set (match_dup 0) - (mult:SI (match_dup 1) - (match_dup 2)))] - "operands[2] = GEN_INT (1 << INTVAL (operands[2]));") + "reload_completed" + [(const_int 0)] + " +{ + rtx pat; + operands[0] = gen_lowpart (SImode, operands[0]); + operands[1] = gen_lowpart (Pmode, operands[1]); + operands[2] = GEN_INT (1 << INTVAL (operands[2])); + pat = gen_rtx_MULT (Pmode, operands[1], operands[2]); + if (Pmode != SImode) + pat = gen_rtx_SUBREG (SImode, pat, 0); + emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat)); + DONE; +}") ;; This pattern can't accept a variable shift count, since shifts by ;; zero don't affect the flags. We assume that shifts by constant @@ -6341,12 +6555,54 @@ "TARGET_HIMODE_MATH" "ix86_expand_binary_operator (ASHIFT, HImode, operands); DONE;") +(define_insn "*ashlhi3_1_lea" + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") + (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0,r") + (match_operand:QI 2 "nonmemory_operand" "cI,M"))) + (clobber (reg:CC 17))] + "!TARGET_PARTIAL_REG_STALL + && ix86_binary_operator_ok (ASHIFT, HImode, operands)" + "* +{ + switch (get_attr_type (insn)) + { + case TYPE_LEA: + return \"#\"; + case TYPE_ALU: + if (operands[2] != const1_rtx) + abort (); + return \"add{w}\\t{%0, %0|%0, %0}\"; + + default: + if (REG_P (operands[2])) + return \"sal{w}\\t{%b2, %0|%0, %b2}\"; + else if (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) == 1 + && (TARGET_PENTIUM || TARGET_PENTIUMPRO)) + return \"sal{w}\\t%0\"; + else + return \"sal{w}\\t{%2, %0|%0, %2}\"; + } +}" + [(set (attr "type") + (cond [(eq_attr "alternative" "1") + (const_string "lea") + (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") + (const_int 0)) + (match_operand 0 "register_operand" "")) + (match_operand 2 "const1_operand" "")) + (const_string "alu") + ] + (const_string "ishift"))) + (set_attr "mode" "HI,SI")]) + (define_insn "*ashlhi3_1" [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "nonmemory_operand" "cI"))) (clobber (reg:CC 17))] - "ix86_binary_operator_ok (ASHIFT, HImode, operands)" + "TARGET_PARTIAL_REG_STALL + && ix86_binary_operator_ok (ASHIFT, HImode, operands)" "* { switch (get_attr_type (insn)) @@ -6429,12 +6685,73 @@ "ix86_expand_binary_operator (ASHIFT, QImode, operands); DONE;") ;; %%% Potential partial reg stall on alternative 2. What to do? + +(define_insn "*ashlqi3_1_lea" + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r,r") + (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,r") + (match_operand:QI 2 "nonmemory_operand" "cI,cI,r"))) + (clobber (reg:CC 17))] + "!TARGET_PARTIAL_REG_STALL + && ix86_binary_operator_ok (ASHIFT, QImode, operands)" + "* +{ + switch (get_attr_type (insn)) + { + case TYPE_LEA: + return \"#\"; + case TYPE_ALU: + if (operands[2] != const1_rtx) + abort (); + if (NON_QI_REG_P (operands[1])) + return \"add{l}\\t{%k0, %k0|%k0, %k0}\"; + else + return \"add{b}\\t{%0, %0|%0, %0}\"; + + default: + if (REG_P (operands[2])) + { + if (get_attr_mode (insn) == MODE_SI) + return \"sal{l}\\t{%b2, %k0|%k0, %b2}\"; + else + return \"sal{b}\\t{%b2, %0|%0, %b2}\"; + } + else if (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) == 1 + && (TARGET_PENTIUM || TARGET_PENTIUMPRO)) + { + if (get_attr_mode (insn) == MODE_SI) + return \"sal{l}\\t%0\"; + else + return \"sal{b}\\t%0\"; + } + else + { + if (get_attr_mode (insn) == MODE_SI) + return \"sal{l}\\t{%2, %k0|%k0, %2}\"; + else + return \"sal{b}\\t{%2, %0|%0, %2}\"; + } + } +}" + [(set (attr "type") + (cond [(eq_attr "alternative" "2") + (const_string "lea") + (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") + (const_int 0)) + (match_operand 0 "register_operand" "")) + (match_operand 2 "const1_operand" "")) + (const_string "alu") + ] + (const_string "ishift"))) + (set_attr "mode" "QI,SI,SI")]) + (define_insn "*ashlqi3_1" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r") (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") (match_operand:QI 2 "nonmemory_operand" "cI,cI"))) (clobber (reg:CC 17))] - "ix86_binary_operator_ok (ASHIFT, QImode, operands)" + "TARGET_PARTIAL_REG_STALL + && ix86_binary_operator_ok (ASHIFT, QImode, operands)" "* { switch (get_attr_type (insn)) |