From: Roger Sayle Date: Thu, 30 Mar 2006 17:47:48 +0000 (+0000) Subject: re PR target/17959 (-mpowerpc64 can cause worse code than without it) X-Git-Tag: releases/gcc-4.2.0~3486 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=79edfde8fb072da763bb08da00ed109a23311f17;p=thirdparty%2Fgcc.git re PR target/17959 (-mpowerpc64 can cause worse code than without it) PR target/17959 * expr.c (emit_group_store): Optimize group stores into a pseudo register by using a paradoxical subreg to initialize the destination if the first or last member of the group specifies a "low part". From-SVN: r112543 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e302bb761383..d7410deb6280 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2006-03-30 Roger Sayle + + PR target/17959 + * expr.c (emit_group_store): Optimize group stores into a pseudo + register by using a paradoxical subreg to initialize the destination + if the first or last member of the group specifies a "low part". + 2006-03-30 Maxim Kuvyrkov PR target/26734 diff --git a/gcc/expr.c b/gcc/expr.c index f579e27c865d..059f08205110 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -1857,7 +1857,7 @@ void emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize) { rtx *tmps, dst; - int start, i; + int start, finish, i; enum machine_mode m = GET_MODE (orig_dst); gcc_assert (GET_CODE (src) == PARALLEL); @@ -1883,11 +1883,12 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize) start = 0; else start = 1; + finish = XVECLEN (src, 0); - tmps = alloca (sizeof (rtx) * XVECLEN (src, 0)); + tmps = alloca (sizeof (rtx) * finish); /* Copy the (probable) hard regs into pseudos. */ - for (i = start; i < XVECLEN (src, 0); i++) + for (i = start; i < finish; i++) { rtx reg = XEXP (XVECEXP (src, 0, i), 0); if (!REG_P (reg) || REGNO (reg) < FIRST_PSEUDO_REGISTER) @@ -1923,14 +1924,56 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize) } else if (!MEM_P (dst) && GET_CODE (dst) != CONCAT) { + enum machine_mode outer = GET_MODE (dst); + enum machine_mode inner; + unsigned int bytepos; + bool done = false; + rtx temp; + if (!REG_P (dst) || REGNO (dst) < FIRST_PSEUDO_REGISTER) - dst = gen_reg_rtx (GET_MODE (orig_dst)); + dst = gen_reg_rtx (outer); + /* Make life a bit easier for combine. */ - emit_move_insn (dst, CONST0_RTX (GET_MODE (orig_dst))); + /* If the first element of the vector is the low part + of the destination mode, use a paradoxical subreg to + initialize the destination. */ + if (start < finish) + { + inner = GET_MODE (tmps[start]); + bytepos = subreg_lowpart_offset (outer, inner); + if (INTVAL (XEXP (XVECEXP (src, 0, start), 1)) == bytepos) + { + temp = simplify_gen_subreg (outer, tmps[start], + inner, bytepos); + emit_move_insn (dst, temp); + done = true; + start++; + } + } + + /* If the first element wasn't the low part, try the last. */ + if (!done + && start < finish - 1) + { + inner = GET_MODE (tmps[finish - 1]); + bytepos = subreg_lowpart_offset (outer, inner); + if (INTVAL (XEXP (XVECEXP (src, 0, finish - 1), 1)) == bytepos) + { + temp = simplify_gen_subreg (outer, tmps[finish - 1], + inner, bytepos); + emit_move_insn (dst, temp); + done = true; + finish--; + } + } + + /* Otherwise, simply initialize the result to zero. */ + if (!done) + emit_move_insn (dst, CONST0_RTX (outer)); } /* Process the pieces. */ - for (i = start; i < XVECLEN (src, 0); i++) + for (i = start; i < finish; i++) { HOST_WIDE_INT bytepos = INTVAL (XEXP (XVECEXP (src, 0, i), 1)); enum machine_mode mode = GET_MODE (tmps[i]);