RE: [PATCH, combine] Try REG_EQUAL for nonzero_bits
From: gcc-patches-ow...@gcc.gnu.org [mailto:gcc-patches- ow...@gcc.gnu.org] On Behalf Of Thomas Preud'homme Based on my understanding of your answer quoted above, I'll commit it as is, despite not having been able to come up with a testcase. I'll wait tomorrow to do so though in case you changed your mind about it. Committed. Best regards, Thomas
RE: [PATCH, combine] Try REG_EQUAL for nonzero_bits
From: Jeff Law [mailto:l...@redhat.com] Sent: Tuesday, April 28, 2015 12:27 AM OK. No need for heroics -- give it a shot, but don't burn an insane amount of time on it. If we can't get to a reasonable testcase, then so be it. Ok, I tried but really didn't managed to create a testcase. I did, however, understand the condition when this patch is helpful. In the function reg_nonzero_bits_for_combine () in combine.c there is a test to check if last_set_nonzero_bits for a given register is still valid. In the case I'm considering, the test evaluates to false because: (i) the register rX whose nonzero bits are being evaluated was set in a previous basic block than the one with the instruction using rX (hence rsp-last_set_label label_tick) (ii) the predecessor of the the basic block for that same insn is not the previous basic block analyzed by combine_instructions (hence label_tick_ebb_start == label_tick) (iii) the register rX is set multiple time (hence REG_N_SETS (REGNO (x)) != 1) Yet, the block being processed is dominated by the SET for rX so there is a REG_EQUAL available to narrow down the set of nonzero bits. Based on my understanding of your answer quoted above, I'll commit it as is, despite not having been able to come up with a testcase. I'll wait tomorrow to do so though in case you changed your mind about it. Best regards, Thomas
RE: [PATCH, combine] Try REG_EQUAL for nonzero_bits
From: Jeff Law [mailto:l...@redhat.com] Sent: Tuesday, April 28, 2015 12:27 AM To: Thomas Preud'homme; 'Eric Botcazou' Cc: gcc-patches@gcc.gnu.org Subject: Re: [PATCH, combine] Try REG_EQUAL for nonzero_bits On 04/27/2015 04:26 AM, Thomas Preud'homme wrote: From: Jeff Law [mailto:l...@redhat.com] Sent: Saturday, April 25, 2015 3:00 AM Do you have a testcase where this change can result in better generated code. If so please add that testcase. It's OK if it's ARM specific. Hi Jeff, Last time I tried I couldn't reduce the code to a small testcase but if I remember well it was mostly due to the problem of finding a good test for creduce (zero extension is not unique enough). I'll try again with a more manual approach and get back to you. OK. No need for heroics -- give it a shot, but don't burn an insane amount of time on it. If we can't get to a reasonable testcase, then so be it. Sadly I couldn't get a testcase. I get almost same sequence of instruction as the program we found the problem into but couldn't get exactly the same. In all the cases I constructed the nonzero_bits info we already have were enough for combine to do its job. I couldn't find what cause this information to be inaccurate. I will try to investigate a bit further on Monday as another pass might not be doing its job properly. Or maybe there's something that prevent information being propagated. Best regards, Thomas
RE: [PATCH, combine] Try REG_EQUAL for nonzero_bits
From: Jeff Law [mailto:l...@redhat.com] Sent: Saturday, April 25, 2015 3:00 AM Do you have a testcase where this change can result in better generated code. If so please add that testcase. It's OK if it's ARM specific. Hi Jeff, Last time I tried I couldn't reduce the code to a small testcase but if I remember well it was mostly due to the problem of finding a good test for creduce (zero extension is not unique enough). I'll try again with a more manual approach and get back to you. Best regards, Thomas
Re: [PATCH, combine] Try REG_EQUAL for nonzero_bits
On 04/27/2015 04:26 AM, Thomas Preud'homme wrote: From: Jeff Law [mailto:l...@redhat.com] Sent: Saturday, April 25, 2015 3:00 AM Do you have a testcase where this change can result in better generated code. If so please add that testcase. It's OK if it's ARM specific. Hi Jeff, Last time I tried I couldn't reduce the code to a small testcase but if I remember well it was mostly due to the problem of finding a good test for creduce (zero extension is not unique enough). I'll try again with a more manual approach and get back to you. OK. No need for heroics -- give it a shot, but don't burn an insane amount of time on it. If we can't get to a reasonable testcase, then so be it. jeff
Re: [PATCH, combine] Try REG_EQUAL for nonzero_bits
On 02/09/2015 07:00 PM, Thomas Preud'homme wrote: And this is part 2. From: gcc-patches-ow...@gcc.gnu.org [mailto:gcc-patches- ow...@gcc.gnu.org] On Behalf Of Eric Botcazou Once this is done, the same thing needs to be applied to XEXP (reg_equal, 0) before it is sent to nonzero_bits. - /* Don't call nonzero_bits if it cannot change anything. */ - if (rsp-nonzero_bits != ~(unsigned HOST_WIDE_INT) 0) - rsp-nonzero_bits |= nonzero_bits (src, nonzero_bits_mode); num = num_sign_bit_copies (SET_SRC (set), GET_MODE (x)); if (rsp-sign_bit_copies == 0 || rsp-sign_bit_copies num) rsp-sign_bit_copies = num; + + /* Don't call nonzero_bits if it cannot change anything. */ + if (rsp-nonzero_bits != ~(unsigned HOST_WIDE_INT) 0) + update_rsp_from_reg_equal (rsp, insn, src, x); Can't we improve on this? rsp-sign_bit_copies is modified both here and in update_rsp_from_reg_equal, but rsp-nonzero_bits is modified only in the latter function. There is no reason for this discrepancy, so they ought to be handled the same way, either entirely here or entirely in the function. So I moved all the handling inside the new function and also added a check before calling num_sign_bit_copies about whether it would give any more information to be consistent with what is done for nonzero_bits. ChangeLog entry is as follows: 2015-02-09 Thomas Preud'homme thomas.preudho...@arm.com * combine.c i(set_nonzero_bits_and_sign_copies): Split code updating rsp-sign_bit_copies and rsp-nonzero_bits into ... (update_rsp_from_reg_equal): This. Also use REG_EQUAL note on src if present to get more accurate information about the number of sign bit copies and non zero bits. Do you have a testcase where this change can result in better generated code. If so please add that testcase. It's OK if it's ARM specific. OK with a testcase. jeff
RE: [PATCH, combine] Try REG_EQUAL for nonzero_bits
And this is part 2. From: gcc-patches-ow...@gcc.gnu.org [mailto:gcc-patches- ow...@gcc.gnu.org] On Behalf Of Eric Botcazou Once this is done, the same thing needs to be applied to XEXP (reg_equal, 0) before it is sent to nonzero_bits. - /* Don't call nonzero_bits if it cannot change anything. */ - if (rsp-nonzero_bits != ~(unsigned HOST_WIDE_INT) 0) - rsp-nonzero_bits |= nonzero_bits (src, nonzero_bits_mode); num = num_sign_bit_copies (SET_SRC (set), GET_MODE (x)); if (rsp-sign_bit_copies == 0 || rsp-sign_bit_copies num) rsp-sign_bit_copies = num; + + /* Don't call nonzero_bits if it cannot change anything. */ + if (rsp-nonzero_bits != ~(unsigned HOST_WIDE_INT) 0) + update_rsp_from_reg_equal (rsp, insn, src, x); Can't we improve on this? rsp-sign_bit_copies is modified both here and in update_rsp_from_reg_equal, but rsp-nonzero_bits is modified only in the latter function. There is no reason for this discrepancy, so they ought to be handled the same way, either entirely here or entirely in the function. So I moved all the handling inside the new function and also added a check before calling num_sign_bit_copies about whether it would give any more information to be consistent with what is done for nonzero_bits. ChangeLog entry is as follows: 2015-02-09 Thomas Preud'homme thomas.preudho...@arm.com * combine.c i(set_nonzero_bits_and_sign_copies): Split code updating rsp-sign_bit_copies and rsp-nonzero_bits into ... (update_rsp_from_reg_equal): This. Also use REG_EQUAL note on src if present to get more accurate information about the number of sign bit copies and non zero bits. diff --git a/gcc/combine.c b/gcc/combine.c index f2b26c2..622279e 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -1660,6 +1660,51 @@ sign_extend_short_imm (rtx src, machine_mode mode, unsigned int prec) } #endif +/* Update RSP for pseudo-register X from INSN's REG_EQUAL note (if one exists) + and SET. */ + +static void +update_rsp_from_reg_equal (reg_stat_type *rsp, rtx_insn *insn, const_rtx set, + rtx x) +{ + rtx reg_equal_note = insn ? find_reg_equal_equiv_note (insn) : NULL_RTX; + unsigned HOST_WIDE_INT bits = 0; + rtx reg_equal = NULL, src = SET_SRC (set); + unsigned int num = 0; + + if (reg_equal_note) +reg_equal = XEXP (reg_equal_note, 0); + +#ifdef SHORT_IMMEDIATES_SIGN_EXTEND + src = sign_extend_short_imm (src, GET_MODE (x), BITS_PER_WORD); + if (reg_equal) +reg_equal = sign_extend_short_imm (reg_equal, GET_MODE (x), BITS_PER_WORD); +#endif + + /* Don't call nonzero_bits if it cannot change anything. */ + if (rsp-nonzero_bits != ~(unsigned HOST_WIDE_INT) 0) +{ + bits = nonzero_bits (src, nonzero_bits_mode); + if (reg_equal bits) + bits = nonzero_bits (reg_equal, nonzero_bits_mode); + rsp-nonzero_bits |= bits; +} + + /* Don't call num_sign_bit_copies if it cannot change anything. */ + if (rsp-sign_bit_copies != 1) +{ + num = num_sign_bit_copies (SET_SRC (set), GET_MODE (x)); + if (reg_equal num != GET_MODE_PRECISION (GET_MODE (x))) + { + unsigned int numeq = num_sign_bit_copies (reg_equal, GET_MODE (x)); + if (num == 0 || numeq num) + num = numeq; + } + if (rsp-sign_bit_copies == 0 || num rsp-sign_bit_copies) + rsp-sign_bit_copies = num; +} +} + /* Called via note_stores. If X is a pseudo that is narrower than HOST_BITS_PER_WIDE_INT and is being set, record what bits are known zero. @@ -1675,7 +1720,6 @@ static void set_nonzero_bits_and_sign_copies (rtx x, const_rtx set, void *data) { rtx_insn *insn = (rtx_insn *) data; - unsigned int num; if (REG_P (x) REGNO (x) = FIRST_PSEUDO_REGISTER @@ -1735,21 +1779,7 @@ set_nonzero_bits_and_sign_copies (rtx x, const_rtx set, void *data) if (SET_DEST (set) == x || (paradoxical_subreg_p (SET_DEST (set)) SUBREG_REG (SET_DEST (set)) == x)) - { - rtx src = SET_SRC (set); - -#ifdef SHORT_IMMEDIATES_SIGN_EXTEND - src = sign_extend_short_imm (src, GET_MODE (x), BITS_PER_WORD); -#endif - - /* Don't call nonzero_bits if it cannot change anything. */ - if (rsp-nonzero_bits != ~(unsigned HOST_WIDE_INT) 0) - rsp-nonzero_bits |= nonzero_bits (src, nonzero_bits_mode); - num = num_sign_bit_copies (SET_SRC (set), GET_MODE (x)); - if (rsp-sign_bit_copies == 0 - || rsp-sign_bit_copies num) - rsp-sign_bit_copies = num; - } + update_rsp_from_reg_equal (rsp, insn, set, x); else { rsp-nonzero_bits = GET_MODE_MASK (GET_MODE (x)); Is this ok for stage 1? Best regards, Thomas
Re: [PATCH, combine] Try REG_EQUAL for nonzero_bits
Thanks for the comments. Patch is updated. diff --git a/gcc/combine.c b/gcc/combine.c index 1808f97..2e865d7 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -1603,6 +1603,28 @@ setup_incoming_promotions (rtx_insn *first) } } +/* Update RSP from INSN's REG_EQUAL note and SRC. */ + +static void +update_rsp_from_reg_equal (reg_stat_type *rsp, rtx_insn *insn, rtx src, rtx x) +{ + rtx reg_equal = insn ? find_reg_equal_equiv_note (insn) : NULL_RTX; + unsigned HOST_WIDE_INT bits = nonzero_bits (src, nonzero_bits_mode); Note that src has taken the SHORT_IMMEDIATES_SIGN_EXTEND path here. + if (reg_equal) +{ + unsigned int num = num_sign_bit_copies (XEXP (reg_equal, 0), + GET_MODE (x)); + bits = nonzero_bits (XEXP (reg_equal, 0), nonzero_bits_mode); But XEXP (reg_equal, 0) hasn't here. If we want to treat the datum of the REG_EQUAL or REG_EQUIV note as equivalent to the SET_SRC (set), and I think we should (see for example combine.c:9650), there is a problem. So I think we should create a new function, something along of: /* If MODE has a precision lower than PREC and SRC is a non-negative constant that would appear negative in MODE, sign-extend SRC for use in nonzero_bits because some machines (maybe most) will actually do the sign-extension and this is the conservative approach. ??? For 2.5, try to tighten up the MD files in this regard instead of this kludge. */ rtx sign_extend_short_imm (rtx src, machine_mode mode, unsigned int prec) { if (GET_MODE_PRECISION (mode) prec CONST_INT_P (src) INTVAL (src) 0 val_signbit_known_set_p (mode, INTVAL (src))) src = GEN_INT (INTVAL (src) | ~GET_MODE_MASK (mode)); return src; } and calls it from combine.c:1702 #ifdef SHORT_IMMEDIATES_SIGN_EXTEND src = sign_extend_short_imm (src, GET_MODE (x), BITS_PER_WORD); #endif and from combine.c:9650 #ifdef SHORT_IMMEDIATES_SIGN_EXTEND tem = sign_extend_short_imm (tem, GET_MODE (x), GET_MODE_PRECISION (mode)); #endif Once this is done, the same thing needs to be applied to XEXP (reg_equal, 0) before it is sent to nonzero_bits. - /* Don't call nonzero_bits if it cannot change anything. */ - if (rsp-nonzero_bits != ~(unsigned HOST_WIDE_INT) 0) - rsp-nonzero_bits |= nonzero_bits (src, nonzero_bits_mode); num = num_sign_bit_copies (SET_SRC (set), GET_MODE (x)); if (rsp-sign_bit_copies == 0 || rsp-sign_bit_copies num) rsp-sign_bit_copies = num; + + /* Don't call nonzero_bits if it cannot change anything. */ + if (rsp-nonzero_bits != ~(unsigned HOST_WIDE_INT) 0) + update_rsp_from_reg_equal (rsp, insn, src, x); Can't we improve on this? rsp-sign_bit_copies is modified both here and in update_rsp_from_reg_equal, but rsp-nonzero_bits is modified only in the latter function. There is no reason for this discrepancy, so they ought to be handled the same way, either entirely here or entirely in the function. -- Eric Botcazou
RE: [PATCH, combine] Try REG_EQUAL for nonzero_bits
-Original Message- From: gcc-patches-ow...@gcc.gnu.org [mailto:gcc-patches- ow...@gcc.gnu.org] On Behalf Of Eric Botcazou Sent: Monday, November 24, 2014 5:41 PM To: Zhenqiang Chen Cc: gcc-patches@gcc.gnu.org Subject: Re: [PATCH, combine] Try REG_EQUAL for nonzero_bits Thanks for the comments. I will compare the two nonzero_bits from src and REG_EQUAL. Then select the smaller one. They are masks so you can simply AND them before ORing the result. Do you know why it use SET_SRC (set) other than src for num_sign_bit_copies? If it is src, I should do the same for num_sign_bit_copies with REG_EQUAL info. Probably historical reasons, let's not try to change that now. You can apply the same treatment to num_sign_bit_copies (you will need a comparison here) while preserving the src vs SET_SRC (set) discrepancy. Thanks for the comments. Patch is updated. diff --git a/gcc/combine.c b/gcc/combine.c index 1808f97..2e865d7 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -1603,6 +1603,28 @@ setup_incoming_promotions (rtx_insn *first) } } +/* Update RSP from INSN's REG_EQUAL note and SRC. */ + +static void +update_rsp_from_reg_equal (reg_stat_type *rsp, rtx_insn *insn, rtx src, rtx x) +{ + rtx reg_equal = insn ? find_reg_equal_equiv_note (insn) : NULL_RTX; + unsigned HOST_WIDE_INT bits = nonzero_bits (src, nonzero_bits_mode); + + if (reg_equal) +{ + unsigned int num = num_sign_bit_copies (XEXP (reg_equal, 0), + GET_MODE (x)); + bits = nonzero_bits (XEXP (reg_equal, 0), nonzero_bits_mode); + rsp-nonzero_bits |= bits; + + if (rsp-sign_bit_copies num) + rsp-sign_bit_copies = num; +} + else +rsp-nonzero_bits |= bits; +} + /* Called via note_stores. If X is a pseudo that is narrower than HOST_BITS_PER_WIDE_INT and is being set, record what bits are known zero. @@ -1698,13 +1720,14 @@ set_nonzero_bits_and_sign_copies (rtx x, const_rtx set, void *data) src = GEN_INT (INTVAL (src) | ~GET_MODE_MASK (GET_MODE (x))); #endif - /* Don't call nonzero_bits if it cannot change anything. */ - if (rsp-nonzero_bits != ~(unsigned HOST_WIDE_INT) 0) - rsp-nonzero_bits |= nonzero_bits (src, nonzero_bits_mode); num = num_sign_bit_copies (SET_SRC (set), GET_MODE (x)); if (rsp-sign_bit_copies == 0 || rsp-sign_bit_copies num) rsp-sign_bit_copies = num; + + /* Don't call nonzero_bits if it cannot change anything. */ + if (rsp-nonzero_bits != ~(unsigned HOST_WIDE_INT) 0) + update_rsp_from_reg_equal (rsp, insn, src, x); } else {
RE: [PATCH, combine] Try REG_EQUAL for nonzero_bits
-Original Message- From: Eric Botcazou [mailto:ebotca...@adacore.com] Sent: Saturday, November 22, 2014 6:15 PM To: Zhenqiang Chen Cc: gcc-patches@gcc.gnu.org Subject: Re: [PATCH, combine] Try REG_EQUAL for nonzero_bits The patch tries to use REG_EQUAL to get more precise info for nonzero_bits, which helps to remove unnecessary zero_extend. Here is an example when compiling Coremark, we have rtx like, (insn 1244 386 388 47 (set (reg:SI 263 [ D.5767 ]) (reg:SI 384 [ D.5767 ])) 786 {*thumb2_movsi_insn} (expr_list:REG_EQUAL (zero_extend:SI (mem:QI (reg/v/f:SI 271 [ memblock ]) [0 *memblock_13(D)+0 S1 A8])) (nil))) from reg:SI 384, we can only know it is a 32-bit value. But from REG_EQUAL, we can know it is an 8-bit value. Then for the following rtx seq, (insn 409 407 410 50 (set (reg:SI 308) (plus:SI (reg:SI 263 [ D.5767 ]) (const_int -48 [0xffd0]))) core_state.c:170 4 {*arm_addsi3} (nil)) (insn 410 409 411 50 (set (reg:SI 309) (zero_extend:SI (subreg:QI (reg:SI 308) 0))) core_state.c:170 812 {thumb2_zero_extendqisi2_v6} (expr_list:REG_DEAD (reg:SI 308) (nil))) the zero_extend for r309 can be optimized by combine pass. This sounds like a good idea. 2014-11-21 Zhenqiang Chen zhenqiang.c...@arm.com * combine.c (set_nonzero_bits_and_sign_copies): Try REG_EQUAL note. diff --git a/gcc/combine.c b/gcc/combine.c index 6a7d16b..68a883b 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -1713,7 +1713,15 @@ set_nonzero_bits_and_sign_copies (rtx x, const_rtx set, void *data) /* Don't call nonzero_bits if it cannot change anything. */ if (rsp-nonzero_bits != ~(unsigned HOST_WIDE_INT) 0) - rsp-nonzero_bits |= nonzero_bits (src, nonzero_bits_mode); + { + rtx reg_equal = insn ? find_reg_note (insn, REG_EQUAL, NULL_RTX) +: NULL_RTX; + if (reg_equal) + rsp-nonzero_bits |= nonzero_bits (XEXP (reg_equal, 0), + nonzero_bits_mode); + else + rsp-nonzero_bits |= nonzero_bits (src, nonzero_bits_mode); + } num = num_sign_bit_copies (SET_SRC (set), GET_MODE (x)); if (rsp-sign_bit_copies == 0 || rsp-sign_bit_copies num) Use find_reg_equal_equiv_note instead. Are you sure that this won't yield inferior results in very peculiar cases? IOW, why not use both sources? Thanks for the comments. I will compare the two nonzero_bits from src and REG_EQUAL. Then select the smaller one. Note that 'src' is massaged just above if SHORT_IMMEDIATES_SIGN_EXTEND is defined so we should probably do it for the note datum too, for example by factoring the code into a function and invoking it. Why not do the same for num_sign_bit_copies? Do you know why it use SET_SRC (set) other than src for num_sign_bit_copies? If it is src, I should do the same for num_sign_bit_copies with REG_EQUAL info. Thanks! -Zhenqiang
Re: [PATCH, combine] Try REG_EQUAL for nonzero_bits
Thanks for the comments. I will compare the two nonzero_bits from src and REG_EQUAL. Then select the smaller one. They are masks so you can simply AND them before ORing the result. Do you know why it use SET_SRC (set) other than src for num_sign_bit_copies? If it is src, I should do the same for num_sign_bit_copies with REG_EQUAL info. Probably historical reasons, let's not try to change that now. You can apply the same treatment to num_sign_bit_copies (you will need a comparison here) while preserving the src vs SET_SRC (set) discrepancy. -- Eric Botcazou
Re: [PATCH, combine] Try REG_EQUAL for nonzero_bits
The patch tries to use REG_EQUAL to get more precise info for nonzero_bits, which helps to remove unnecessary zero_extend. Here is an example when compiling Coremark, we have rtx like, (insn 1244 386 388 47 (set (reg:SI 263 [ D.5767 ]) (reg:SI 384 [ D.5767 ])) 786 {*thumb2_movsi_insn} (expr_list:REG_EQUAL (zero_extend:SI (mem:QI (reg/v/f:SI 271 [ memblock ]) [0 *memblock_13(D)+0 S1 A8])) (nil))) from reg:SI 384, we can only know it is a 32-bit value. But from REG_EQUAL, we can know it is an 8-bit value. Then for the following rtx seq, (insn 409 407 410 50 (set (reg:SI 308) (plus:SI (reg:SI 263 [ D.5767 ]) (const_int -48 [0xffd0]))) core_state.c:170 4 {*arm_addsi3} (nil)) (insn 410 409 411 50 (set (reg:SI 309) (zero_extend:SI (subreg:QI (reg:SI 308) 0))) core_state.c:170 812 {thumb2_zero_extendqisi2_v6} (expr_list:REG_DEAD (reg:SI 308) (nil))) the zero_extend for r309 can be optimized by combine pass. This sounds like a good idea. 2014-11-21 Zhenqiang Chen zhenqiang.c...@arm.com * combine.c (set_nonzero_bits_and_sign_copies): Try REG_EQUAL note. diff --git a/gcc/combine.c b/gcc/combine.c index 6a7d16b..68a883b 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -1713,7 +1713,15 @@ set_nonzero_bits_and_sign_copies (rtx x, const_rtx set, void *data) /* Don't call nonzero_bits if it cannot change anything. */ if (rsp-nonzero_bits != ~(unsigned HOST_WIDE_INT) 0) - rsp-nonzero_bits |= nonzero_bits (src, nonzero_bits_mode); + { + rtx reg_equal = insn ? find_reg_note (insn, REG_EQUAL, NULL_RTX) + : NULL_RTX; + if (reg_equal) + rsp-nonzero_bits |= nonzero_bits (XEXP (reg_equal, 0), +nonzero_bits_mode); + else + rsp-nonzero_bits |= nonzero_bits (src, nonzero_bits_mode); + } num = num_sign_bit_copies (SET_SRC (set), GET_MODE (x)); if (rsp-sign_bit_copies == 0 || rsp-sign_bit_copies num) Use find_reg_equal_equiv_note instead. Are you sure that this won't yield inferior results in very peculiar cases? IOW, why not use both sources? Note that 'src' is massaged just above if SHORT_IMMEDIATES_SIGN_EXTEND is defined so we should probably do it for the note datum too, for example by factoring the code into a function and invoking it. Why not do the same for num_sign_bit_copies? -- Eric Botcazou