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
This commit is contained in:
parent
ad98bad83e
commit
6ec6d558ed
|
@ -1,6 +1,14 @@
|
|||
Thu Apr 15 01:03:21 1999 Jan Hubicka <hubicka@freesoft.cz>
|
||||
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
|
||||
memory_address_displacement_length instead of 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)
|
|||
|
||||
/* Stores stalls one cycle longer than other insns. */
|
||||
if (is_fp_insn (insn) && cost && is_fp_store (dep_insn))
|
||||
cost++;
|
||||
cost++;
|
||||
|
||||
case PROCESSOR_K6:
|
||||
default:
|
||||
|
@ -5543,34 +5543,50 @@ x86_adjust_cost (insn, link, dep_insn, cost)
|
|||
TARGET_DOUBLE_WITH_ADD. */
|
||||
|
||||
char *
|
||||
output_ashlsi3 (operands)
|
||||
rtx *operands;
|
||||
output_ashl (insn, operands)
|
||||
rtx insn, *operands;
|
||||
{
|
||||
/* Handle case where srcreg != dstreg. */
|
||||
if (REG_P (operands[0]) && REGNO (operands[0]) != REGNO (operands[1]))
|
||||
{
|
||||
if (TARGET_DOUBLE_WITH_ADD && INTVAL (operands[2]) == 1)
|
||||
{
|
||||
output_asm_insn (AS2 (mov%L0,%1,%0), operands);
|
||||
return AS2 (add%L0,%1,%0);
|
||||
}
|
||||
switch (GET_MODE (operands[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
|
||||
{
|
||||
CC_STATUS_INIT;
|
||||
{
|
||||
CC_STATUS_INIT;
|
||||
|
||||
/* This should be extremely rare (impossible?). We can not encode a
|
||||
shift of the stack pointer using an lea instruction. So copy the
|
||||
stack pointer into the destination register and use an lea. */
|
||||
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];
|
||||
}
|
||||
|
||||
/* 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])));
|
||||
return AS2 (lea%L0,%a1,%0);
|
||||
return AS2 (lea%L0,%a1,%k0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5578,17 +5594,47 @@ output_ashlsi3 (operands)
|
|||
|
||||
/* Handle variable shift. */
|
||||
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. */
|
||||
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
|
||||
/* ??? Currently disabled. reg-stack currently stomps on the mode of
|
||||
each insn. Thus, we can not easily detect when we should use lea to
|
||||
improve issue characteristics. Until reg-stack is fixed, fall back to
|
||||
sal instruction for Pentiums to avoid AGI stall. */
|
||||
/* ??? Currently disabled. Because our model of Pentium is far from being
|
||||
exact, this change will need some benchmarking. */
|
||||
/* 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
|
||||
TImode for a U pipe, and !TImode for a V pipe instruction). */
|
||||
|
@ -5600,14 +5646,30 @@ output_ashlsi3 (operands)
|
|||
&& GET_MODE (insn) != TImode)
|
||||
{
|
||||
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])));
|
||||
return AS2 (lea%L0,%a1,%0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 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
|
||||
|
|
|
@ -2765,7 +2765,7 @@ extern char *output_int_conditional_move ();
|
|||
extern char *output_fp_conditional_move ();
|
||||
extern int ix86_can_use_return_insn_p ();
|
||||
extern int small_shift_operand ();
|
||||
extern char *output_ashlsi3 ();
|
||||
extern char *output_ashl ();
|
||||
extern int memory_address_info ();
|
||||
|
||||
#ifdef NOTYET
|
||||
|
|
|
@ -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.
|
||||
;; This is kept as a separate pattern so that regmove can optimize cases
|
||||
;; where we know the source and destination must match.
|
||||
;;
|
||||
;; 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.
|
||||
|
||||
(define_insn ""
|
||||
[(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
|
||||
(ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,r")
|
||||
(match_operand:SI 2 "small_shift_operand" "M,M")))]
|
||||
"! optimize_size"
|
||||
"* return output_ashlsi3 (operands);")
|
||||
"* return output_ashl (insn, operands);")
|
||||
|
||||
;; Generic left shift pattern to catch all cases not handled by the
|
||||
;; shift pattern above.
|
||||
|
@ -5099,58 +5114,37 @@ byte_xor_operation:
|
|||
(ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0")
|
||||
(match_operand:SI 2 "nonmemory_operand" "cI")))]
|
||||
""
|
||||
"* return output_ashlsi3 (operands);")
|
||||
"* return output_ashl (insn, operands);")
|
||||
|
||||
(define_insn "ashlhi3"
|
||||
(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 ""
|
||||
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
|
||||
(ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
|
||||
(match_operand:HI 2 "nonmemory_operand" "cI")))]
|
||||
""
|
||||
"*
|
||||
{
|
||||
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);
|
||||
}
|
||||
"* return output_ashl (insn, operands);")
|
||||
|
||||
if (REG_P (operands[0]) && operands[2] == const1_rtx)
|
||||
{
|
||||
if (i386_cc_probably_useless_p (insn))
|
||||
{
|
||||
CC_STATUS_INIT;
|
||||
return AS2 (add%L0,%k0,%k0);
|
||||
}
|
||||
return AS2 (add%W0,%0,%0);
|
||||
}
|
||||
(define_insn ""
|
||||
[(set (match_operand:QI 0 "nonimmediate_operand" "=q,q")
|
||||
(ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,q")
|
||||
(match_operand:QI 2 "small_shift_operand" "M,M")))]
|
||||
"! optimize_size"
|
||||
"* return output_ashl (insn, operands);")
|
||||
|
||||
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")
|
||||
(ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0")
|
||||
(match_operand:QI 2 "nonmemory_operand" "cI")))]
|
||||
""
|
||||
"*
|
||||
{
|
||||
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);
|
||||
}")
|
||||
"* return output_ashl (insn, operands);")
|
||||
|
||||
;; See comment above `ashldi3' about how this works.
|
||||
|
||||
|
|
Loading…
Reference in New Issue