On 11/17/2011 10:25 AM, Richard Henderson wrote: > On 11/17/2011 12:37 AM, Alan Modra wrote: >> - oldval = convert_modes (SImode, mode, oldval, 1); >> + oldval = gen_reg_rtx (SImode); >> + convert_move (oldval, orig, 1); >> oldval = expand_simple_binop (SImode, ASHIFT, oldval, shift, >> oldval, 1, OPTAB_LIB_WIDEN); > > Gah. From convert_modes, oldval is a subreg, and modifying that > subreg gets us into all sorts of trouble. The fix should be as > simple as > > - oldval, 1, OPTAB_LIB_WIDEN); > + NULL_RTX, 1, OPTAB_LIB_WIDEN); > > so that we don't write back into the subreg.
Like so. Tested on ppc64-linux and committed. r~
commit 75e213a662f12e22304ecde01e8311b8e3390739 Author: Richard Henderson <r...@twiddle.net> Date: Thu Nov 17 14:07:01 2011 -0800 Fix subreg clobber after convert_modes. If we've got a (subreg/s/u:QI (reg:DI x)) and we use convert_modes, we'll still wind up with (subreg/s/u:SI (reg:DI x)). Having that be the destination of a further expand_binop is incorrect. Force the use of a new pseudo. * config/rs6000/rs6000.c (rs6000_expand_atomic_compare_and_swap): Get new pseudo for target after convert_modes. (rs6000_expand_atomic_exchange, rs6000_expand_atomic_op): Likewise. diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 89c2ea0..f01353b 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -17341,12 +17341,12 @@ rs6000_expand_atomic_compare_and_swap (rtx operands[]) /* Shift and mask OLDVAL into position with the word. */ oldval = convert_modes (SImode, mode, oldval, 1); oldval = expand_simple_binop (SImode, ASHIFT, oldval, shift, - oldval, 1, OPTAB_LIB_WIDEN); + NULL_RTX, 1, OPTAB_LIB_WIDEN); /* Shift and mask NEWVAL into position within the word. */ newval = convert_modes (SImode, mode, newval, 1); newval = expand_simple_binop (SImode, ASHIFT, newval, shift, - newval, 1, OPTAB_LIB_WIDEN); + NULL_RTX, 1, OPTAB_LIB_WIDEN); /* Prepare to adjust the return value. */ retval = gen_reg_rtx (SImode); @@ -17434,7 +17434,7 @@ rs6000_expand_atomic_exchange (rtx operands[]) /* Shift and mask VAL into position with the word. */ val = convert_modes (SImode, mode, val, 1); val = expand_simple_binop (SImode, ASHIFT, val, shift, - val, 1, OPTAB_LIB_WIDEN); + NULL_RTX, 1, OPTAB_LIB_WIDEN); /* Prepare to adjust the return value. */ retval = gen_reg_rtx (SImode); @@ -17487,7 +17487,7 @@ rs6000_expand_atomic_op (enum rtx_code code, rtx mem, rtx val, /* Shift and mask VAL into position with the word. */ val = convert_modes (SImode, mode, val, 1); val = expand_simple_binop (SImode, ASHIFT, val, shift, - val, 1, OPTAB_LIB_WIDEN); + NULL_RTX, 1, OPTAB_LIB_WIDEN); switch (code) {