Commit 58787064 by Jan Hubicka Committed by Jan Hubicka

* 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
parent 8acb2f24
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> Sun Jul 30 20:51:25 MET DST 2000 Jan Hubicka <jh@suse.cz>
* recog.c (general_operand, nonimmediate_operand): Accept * recog.c (general_operand, nonimmediate_operand): Accept
......
...@@ -3740,6 +3740,102 @@ ...@@ -3740,6 +3740,102 @@
[(set_attr "type" "lea") [(set_attr "type" "lea")
(set_attr "mode" "SI")]) (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" (define_insn "*addsi_1"
[(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r") [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r")
(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r") (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r")
...@@ -3796,16 +3892,29 @@ ...@@ -3796,16 +3892,29 @@
;; Convert lea to the lea pattern to avoid flags dependency. ;; Convert lea to the lea pattern to avoid flags dependency.
(define_split (define_split
[(set (match_operand:SI 0 "register_operand" "") [(set (match_operand 0 "register_operand" "")
(plus:SI (match_operand:SI 1 "register_operand" "") (plus (match_operand 1 "register_operand" "")
(match_operand:SI 2 "nonmemory_operand" ""))) (match_operand 2 "nonmemory_operand" "")))
(clobber (reg:CC 17))] (clobber (reg:CC 17))]
"reload_completed "reload_completed"
&& true_regnum (operands[0]) != true_regnum (operands[1])" [(const_int 0)]
[(set (match_dup 0) "
(plus:SI (match_dup 1) {
(match_dup 2)))] 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" (define_insn "*addsi_2"
[(set (reg 17) [(set (reg 17)
...@@ -3883,12 +3992,57 @@ ...@@ -3883,12 +3992,57 @@
;; type optimizations enabled by define-splits. This is not important ;; type optimizations enabled by define-splits. This is not important
;; for PII, and in fact harmful because of partial register stalls. ;; 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" (define_insn "*addhi_1"
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
(plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
(match_operand:HI 2 "general_operand" "ri,rm"))) (match_operand:HI 2 "general_operand" "ri,rm")))
(clobber (reg:CC 17))] (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)) switch (get_attr_type (insn))
...@@ -3986,12 +4140,64 @@ ...@@ -3986,12 +4140,64 @@
"ix86_expand_binary_operator (PLUS, QImode, operands); DONE;") "ix86_expand_binary_operator (PLUS, QImode, operands); DONE;")
;; %%% Potential partial reg stall on alternative 2. What to do? ;; %%% 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" (define_insn "*addqi_1"
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r") [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r")
(plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0") (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
(match_operand:QI 2 "general_operand" "qn,qmn,rn"))) (match_operand:QI 2 "general_operand" "qn,qmn,rn")))
(clobber (reg:CC 17))] (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); int widen = (which_alternative == 2);
...@@ -6279,16 +6485,24 @@ ...@@ -6279,16 +6485,24 @@
;; Convert lea to the lea pattern to avoid flags dependency. ;; Convert lea to the lea pattern to avoid flags dependency.
(define_split (define_split
[(set (match_operand:SI 0 "register_operand" "") [(set (match_operand 0 "register_operand" "")
(ashift:SI (match_operand:SI 1 "register_operand" "") (ashift (match_operand 1 "register_operand" "")
(match_operand:QI 2 "immediate_operand" ""))) (match_operand:QI 2 "const_int_operand" "")))
(clobber (reg:CC 17))] (clobber (reg:CC 17))]
"reload_completed "reload_completed"
&& true_regnum (operands[0]) != true_regnum (operands[1])" [(const_int 0)]
[(set (match_dup 0) "
(mult:SI (match_dup 1) {
(match_dup 2)))] rtx pat;
"operands[2] = GEN_INT (1 << INTVAL (operands[2]));") 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 ;; This pattern can't accept a variable shift count, since shifts by
;; zero don't affect the flags. We assume that shifts by constant ;; zero don't affect the flags. We assume that shifts by constant
...@@ -6341,12 +6555,54 @@ ...@@ -6341,12 +6555,54 @@
"TARGET_HIMODE_MATH" "TARGET_HIMODE_MATH"
"ix86_expand_binary_operator (ASHIFT, HImode, operands); DONE;") "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" (define_insn "*ashlhi3_1"
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm") [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
(ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0") (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "nonmemory_operand" "cI"))) (match_operand:QI 2 "nonmemory_operand" "cI")))
(clobber (reg:CC 17))] (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)) switch (get_attr_type (insn))
...@@ -6429,12 +6685,73 @@ ...@@ -6429,12 +6685,73 @@
"ix86_expand_binary_operator (ASHIFT, QImode, operands); DONE;") "ix86_expand_binary_operator (ASHIFT, QImode, operands); DONE;")
;; %%% Potential partial reg stall on alternative 2. What to do? ;; %%% 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" (define_insn "*ashlqi3_1"
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r") [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r")
(ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "cI,cI"))) (match_operand:QI 2 "nonmemory_operand" "cI,cI")))
(clobber (reg:CC 17))] (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)) switch (get_attr_type (insn))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment