summaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>1999-04-15 01:28:04 +0000
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>1999-04-15 01:28:04 +0000
commit73730883fe0f9874b1a30a1ba8ab4fe1d6b0768b (patch)
treeb8c13a2285138948aa5081bd3b92d4bcbe478ad2 /gcc/config
parent287e15c8200e784bd7811d358a405e36a7789fac (diff)
downloadgcc-73730883fe0f9874b1a30a1ba8ab4fe1d6b0768b.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@26467 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/i386/i386.c102
-rw-r--r--gcc/config/i386/i386.h2
-rw-r--r--gcc/config/i386/i386.md78
3 files changed, 119 insertions, 63 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 5665800bcb3..50acbb1c0ed 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -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
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 1d752c7b472..a455d2d24f0 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -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
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index da131099ec5..39a06f2b233 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -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 ""
+ [(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")
(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);
- }
-
- 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 ""
+ [(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);")
-(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.