Commit 6ec6d558 by Jan Hubicka Committed by Jeff Law

i386.md (ashlsi patterns): Call output_ashl instead of output_ashlsi3.

        * i386.md (ashlsi patterns): Call output_ashl instead of output_ashlsi3.
        (ashlqi): Use expander, separate LEA and SAL / ADD patterns; call
        output_ashl.
        (ashlhi): Likewise.
        * i386.h (output_ashl): Renamed from output_ashlsi3.
        * i386.c (output_ashl): Likewise; support HImode and QImode operands
        as well.

Co-Authored-By: Jeffrey A Law <law@cygnus.com>

From-SVN: r26467
parent ad98bad8
Thu Apr 15 01:03:21 1999 Jan Hubicka <hubicka@freesoft.cz> Thu Apr 15 01:03:21 1999 Jan Hubicka <hubicka@freesoft.cz>
Jeff Law <law@cygnus.com> Jeff Law <law@cygnus.com>
* i386.md (ashlsi patterns): Call output_ashl instead of output_ashlsi3.
(ashlqi): Use expander, separate LEA and SAL / ADD patterns; call
output_ashl.
(ashlhi): Likewise.
* i386.h (output_ashl): Renamed from output_ashlsi3.
* i386.c (output_ashl): Likewise; support HImode and QImode operands
as well.
* i386.md (notsi, nothi, xorsi, xorhi, and xorqi patterns): Call * i386.md (notsi, nothi, xorsi, xorhi, and xorqi patterns): Call
memory_address_displacement_length instead of memory_address_length. memory_address_displacement_length instead of memory_address_length.
* i386.c (memory_address_info): Renamed from memory_address_length. * i386.c (memory_address_info): Renamed from memory_address_length.
......
...@@ -5497,7 +5497,7 @@ x86_adjust_cost (insn, link, dep_insn, cost) ...@@ -5497,7 +5497,7 @@ x86_adjust_cost (insn, link, dep_insn, cost)
/* Stores stalls one cycle longer than other insns. */ /* Stores stalls one cycle longer than other insns. */
if (is_fp_insn (insn) && cost && is_fp_store (dep_insn)) if (is_fp_insn (insn) && cost && is_fp_store (dep_insn))
cost++; cost++;
case PROCESSOR_K6: case PROCESSOR_K6:
default: default:
...@@ -5543,34 +5543,50 @@ x86_adjust_cost (insn, link, dep_insn, cost) ...@@ -5543,34 +5543,50 @@ x86_adjust_cost (insn, link, dep_insn, cost)
TARGET_DOUBLE_WITH_ADD. */ TARGET_DOUBLE_WITH_ADD. */
char * char *
output_ashlsi3 (operands) output_ashl (insn, operands)
rtx *operands; rtx insn, *operands;
{ {
/* Handle case where srcreg != dstreg. */ /* Handle case where srcreg != dstreg. */
if (REG_P (operands[0]) && REGNO (operands[0]) != REGNO (operands[1])) if (REG_P (operands[0]) && REGNO (operands[0]) != REGNO (operands[1]))
{ {
if (TARGET_DOUBLE_WITH_ADD && INTVAL (operands[2]) == 1) if (TARGET_DOUBLE_WITH_ADD && INTVAL (operands[2]) == 1)
{ switch (GET_MODE (operands[0]))
output_asm_insn (AS2 (mov%L0,%1,%0), operands); {
return AS2 (add%L0,%1,%0); case SImode:
} output_asm_insn (AS2 (mov%L0,%1,%0), operands);
return AS2 (add%L0,%1,%0);
case HImode:
output_asm_insn (AS2 (mov%L0,%k1,%k0), operands);
if (i386_cc_probably_useless_p (insn))
{
CC_STATUS_INIT;
return AS2 (add%L0,%k1,%k0);
}
return AS2 (add%W0,%k1,%k0);
case QImode:
output_asm_insn (AS2 (mov%B0,%1,%0), operands);
return AS2 (add%B0,%1,%0);
default:
abort ();
}
else else
{ {
CC_STATUS_INIT; CC_STATUS_INIT;
/* This should be extremely rare (impossible?). We can not encode a /* This should be extremely rare (impossible?). We can not encode a
shift of the stack pointer using an lea instruction. So copy the shift of the stack pointer using an lea instruction. So copy the
stack pointer into the destination register and use an lea. */ stack pointer into the destination register and use an lea. */
if (operands[1] == stack_pointer_rtx) if (operands[1] == stack_pointer_rtx)
{ {
output_asm_insn (AS2 (mov%L0,%1,%0), operands); output_asm_insn (AS2 (mov%L0,%k1,%k0), operands);
operands[1] = operands[0]; operands[1] = operands[0];
} }
/* For shifts up to and including 3 bits, use lea. */ /* For shifts up to and including 3 bits, use lea. */
operands[1] = gen_rtx_MULT (SImode, operands[1], operands[1] = gen_rtx_MULT (SImode,
gen_rtx_REG (SImode, REGNO (operands[1])),
GEN_INT (1 << INTVAL (operands[2]))); GEN_INT (1 << INTVAL (operands[2])));
return AS2 (lea%L0,%a1,%0); return AS2 (lea%L0,%a1,%k0);
} }
} }
...@@ -5578,17 +5594,47 @@ output_ashlsi3 (operands) ...@@ -5578,17 +5594,47 @@ output_ashlsi3 (operands)
/* Handle variable shift. */ /* Handle variable shift. */
if (REG_P (operands[2])) if (REG_P (operands[2]))
return AS2 (sal%L0,%b2,%0); switch (GET_MODE (operands[0]))
{
case SImode:
return AS2 (sal%L0,%b2,%0);
case HImode:
if (REG_P (operands[0]) && i386_cc_probably_useless_p (insn))
{
CC_STATUS_INIT;
return AS2 (sal%L0,%b2,%k0);
}
else
return AS2 (sal%W0,%b2,%0);
case QImode:
return AS2 (sal%B0,%b2,%0);
default:
abort ();
}
/* Always perform shift by 1 using an add instruction. */ /* Always perform shift by 1 using an add instruction. */
if (REG_P (operands[0]) && operands[2] == const1_rtx) if (REG_P (operands[0]) && operands[2] == const1_rtx)
return AS2 (add%L0,%0,%0); switch (GET_MODE (operands[0]))
{
case SImode:
return AS2 (add%L0,%0,%0);
case HImode:
if (REG_P (operands[0]) && i386_cc_probably_useless_p (insn))
{
CC_STATUS_INIT;
return AS2 (add%L0,%k0,%k0);
}
else
return AS2 (add%W0,%0,%0);
case QImode:
return AS2 (add%B0,%0,%0);
default:
abort ();
}
#if 0 #if 0
/* ??? Currently disabled. reg-stack currently stomps on the mode of /* ??? Currently disabled. Because our model of Pentium is far from being
each insn. Thus, we can not easily detect when we should use lea to exact, this change will need some benchmarking. */
improve issue characteristics. Until reg-stack is fixed, fall back to
sal instruction for Pentiums to avoid AGI stall. */
/* Shift reg by 2 or 3 use an lea instruction for Pentium if this is /* Shift reg by 2 or 3 use an lea instruction for Pentium if this is
insn is expected to issue into the V pipe (the insn's mode will be insn is expected to issue into the V pipe (the insn's mode will be
TImode for a U pipe, and !TImode for a V pipe instruction). */ TImode for a U pipe, and !TImode for a V pipe instruction). */
...@@ -5600,14 +5646,30 @@ output_ashlsi3 (operands) ...@@ -5600,14 +5646,30 @@ output_ashlsi3 (operands)
&& GET_MODE (insn) != TImode) && GET_MODE (insn) != TImode)
{ {
CC_STATUS_INIT; CC_STATUS_INIT;
operands[1] = gen_rtx_MULT (SImode, operands[1], operands[1] = gen_rtx_MULT (SImode, gen_rtx_REG (SImode, REGNO (operands[1])),
GEN_INT (1 << INTVAL (operands[2]))); GEN_INT (1 << INTVAL (operands[2])));
return AS2 (lea%L0,%a1,%0); return AS2 (lea%L0,%a1,%0);
} }
#endif #endif
/* Otherwise use a shift instruction. */ /* Otherwise use a shift instruction. */
return AS2 (sal%L0,%2,%0); switch (GET_MODE (operands[0]))
{
case SImode:
return AS2 (sal%L0,%2,%0);
case HImode:
if (REG_P (operands[0]) && i386_cc_probably_useless_p (insn))
{
CC_STATUS_INIT;
return AS2 (sal%L0,%2,%k0);
}
else
return AS2 (sal%W0,%2,%0);
case QImode:
return AS2 (sal%B0,%2,%0);
default:
abort ();
}
} }
/* Given the memory address ADDR, calculate the length of the address or /* Given the memory address ADDR, calculate the length of the address or
......
...@@ -2765,7 +2765,7 @@ extern char *output_int_conditional_move (); ...@@ -2765,7 +2765,7 @@ extern char *output_int_conditional_move ();
extern char *output_fp_conditional_move (); extern char *output_fp_conditional_move ();
extern int ix86_can_use_return_insn_p (); extern int ix86_can_use_return_insn_p ();
extern int small_shift_operand (); extern int small_shift_operand ();
extern char *output_ashlsi3 (); extern char *output_ashl ();
extern int memory_address_info (); extern int memory_address_info ();
#ifdef NOTYET #ifdef NOTYET
......
...@@ -5079,18 +5079,33 @@ byte_xor_operation: ...@@ -5079,18 +5079,33 @@ byte_xor_operation:
"" ""
"") "")
(define_expand "ashlhi3"
[(set (match_operand:HI 0 "nonimmediate_operand" "")
(ashift:HI (match_operand:HI 1 "nonimmediate_operand" "")
(match_operand:HI 2 "nonmemory_operand" "")))]
""
"")
(define_expand "ashlqi3"
[(set (match_operand:QI 0 "nonimmediate_operand" "")
(ashift:QI (match_operand:QI 1 "nonimmediate_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))]
""
"")
;; Pattern for shifts which can be encoded into an lea instruction. ;; Pattern for shifts which can be encoded into an lea instruction.
;; This is kept as a separate pattern so that regmove can optimize cases ;; This is kept as a separate pattern so that regmove can optimize cases
;; where we know the source and destination must match. ;; where we know the source and destination must match.
;; ;;
;; Do not expose this pattern when optimizing for size since we never want ;; Do not expose this pattern when optimizing for size since we never want
;; to use lea when optimizing for size since mov+sal is smaller than lea. ;; to use lea when optimizing for size since mov+sal is smaller than lea.
(define_insn "" (define_insn ""
[(set (match_operand:SI 0 "nonimmediate_operand" "=r,r") [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
(ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,r") (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,r")
(match_operand:SI 2 "small_shift_operand" "M,M")))] (match_operand:SI 2 "small_shift_operand" "M,M")))]
"! optimize_size" "! optimize_size"
"* return output_ashlsi3 (operands);") "* return output_ashl (insn, operands);")
;; Generic left shift pattern to catch all cases not handled by the ;; Generic left shift pattern to catch all cases not handled by the
;; shift pattern above. ;; shift pattern above.
...@@ -5099,58 +5114,37 @@ byte_xor_operation: ...@@ -5099,58 +5114,37 @@ byte_xor_operation:
(ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0") (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0")
(match_operand:SI 2 "nonmemory_operand" "cI")))] (match_operand:SI 2 "nonmemory_operand" "cI")))]
"" ""
"* return output_ashlsi3 (operands);") "* return output_ashl (insn, operands);")
(define_insn ""
[(set (match_operand:HI 0 "nonimmediate_operand" "=r,r")
(ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0,r")
(match_operand:HI 2 "small_shift_operand" "M,M")))]
"! optimize_size"
"* return output_ashl (insn, operands);")
(define_insn "ashlhi3" (define_insn ""
[(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:HI 2 "nonmemory_operand" "cI")))] (match_operand:HI 2 "nonmemory_operand" "cI")))]
"" ""
"* "* return output_ashl (insn, operands);")
{
if (REG_P (operands[2]))
{
if (REG_P (operands[0]) && i386_cc_probably_useless_p (insn))
{
CC_STATUS_INIT;
return AS2 (sal%L0,%b2,%k0);
}
return AS2 (sal%W0,%b2,%0);
}
if (REG_P (operands[0]) && operands[2] == const1_rtx) (define_insn ""
{ [(set (match_operand:QI 0 "nonimmediate_operand" "=q,q")
if (i386_cc_probably_useless_p (insn)) (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,q")
{ (match_operand:QI 2 "small_shift_operand" "M,M")))]
CC_STATUS_INIT; "! optimize_size"
return AS2 (add%L0,%k0,%k0); "* return output_ashl (insn, operands);")
}
return AS2 (add%W0,%0,%0);
}
if (REG_P (operands[0]) && i386_cc_probably_useless_p (insn))
{
CC_STATUS_INIT;
return AS2 (sal%L0,%2,%k0);
}
return AS2 (sal%W0,%2,%0);
}")
(define_insn "ashlqi3" ;; Generic left shift pattern to catch all cases not handled by the
;; shift pattern above.
(define_insn ""
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm") [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
(ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0") (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "nonmemory_operand" "cI")))] (match_operand:QI 2 "nonmemory_operand" "cI")))]
"" ""
"* "* return output_ashl (insn, operands);")
{
if (REG_P (operands[2]))
return AS2 (sal%B0,%b2,%0);
if (REG_P (operands[0]) && operands[2] == const1_rtx)
return AS2 (add%B0,%0,%0);
return AS2 (sal%B0,%2,%0);
}")
;; See comment above `ashldi3' about how this works. ;; See comment above `ashldi3' about how this works.
......
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