From: Jan Hubicka Date: Thu, 15 Apr 1999 01:28:04 +0000 (+0200) Subject: i386.md (ashlsi patterns): Call output_ashl instead of output_ashlsi3. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6ec6d558ed34e6b31a5b984cf6fb9ead6a6ac7b1;p=gcc.git 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 From-SVN: r26467 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3739e5f3de8..30d9a68c276 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,6 +1,14 @@ Thu Apr 15 01:03:21 1999 Jan Hubicka Jeff Law + * 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. 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.