On Thu, May 22, 2014 at 08:01:45PM +1000, Kugan wrote: > --- a/gcc/expr.c > +++ b/gcc/expr.c > @@ -328,7 +328,8 @@ convert_move (rtx to, rtx from, int unsignedp) > if (GET_CODE (from) == SUBREG && SUBREG_PROMOTED_VAR_P (from) > && (GET_MODE_PRECISION (GET_MODE (SUBREG_REG (from))) > >= GET_MODE_PRECISION (to_mode)) > - && SUBREG_PROMOTED_UNSIGNED_P (from) == unsignedp) > + && (SUBREG_PROMOTED_UNSIGNED_P (from) == 2 > + || SUBREG_PROMOTED_UNSIGNED_P (from) == unsignedp)) > from = gen_lowpart (to_mode, from), from_mode = to_mode; > > gcc_assert (GET_CODE (to) != SUBREG || !SUBREG_PROMOTED_VAR_P (to));
Yeah, something like that, though you'd need to tweak all places where SUBREG_PROMOTED_UNSIGNED_P is used, not just this one. > @@ -9498,7 +9544,11 @@ expand_expr_real_1 (tree exp, rtx target, enum > machine_mode tmode, > > temp = gen_lowpart_SUBREG (mode, decl_rtl); > SUBREG_PROMOTED_VAR_P (temp) = 1; > - SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp); > + if (is_value_extended (ssa_name, mode, !unsignedp)) > + SUBREG_PROMOTED_UNSIGNED_SET (temp, 2); > + else > + SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp); > + > return temp; > } This will not do what you want, most of the SUBREGs right now are not SUBREG_PROMOTED_VAR_P, the point was to 1) come up with a testcase where you believe this optimization would be useful and you get that you were talking about SUBREG created (don't remember seeing it) 2) find out where that subreg is created, and do set the SUBREG_PROMOTED_VAR_P there if the range info tells you it is ok (all 3 possibilities, either that it is known to be already zero, or sign, or both zero and sign extended). > > diff --git a/gcc/rtl.h b/gcc/rtl.h > index 10ae1e9..f34a7b5 100644 > --- a/gcc/rtl.h > +++ b/gcc/rtl.h > @@ -299,7 +299,7 @@ struct GTY((chain_next ("RTX_NEXT (&%h)"), > 1 in a CONCAT is VAL_EXPR_IS_CLOBBERED in var-tracking.c. > 1 in a preserved VALUE is PRESERVED_VALUE_P in cselib.c. > 1 in a clobber temporarily created for LRA. */ > - unsigned int unchanging : 1; > + unsigned int unchanging : 2; > /* 1 in a MEM or ASM_OPERANDS expression if the memory reference is > volatile. > 1 in an INSN, CALL_INSN, JUMP_INSN, CODE_LABEL, BARRIER, or NOTE > if it has been deleted. No way. SUBREG_PROMOTED_UNSIGNED_P right now resides in two separate bits, volatil and unchanging. Right now volatile != 0, unchanging ignored is -1, volatile == 0, then the value is unchanging. What I meant is change this representation, e.g. to x->volatil * 2 + x->unchanging - 1 so you can represent the values -1, 0, 1, 2 in there. Of course, adjust SUBREG_PROMOTED_UNSIGNED_SET correspondingly too. As SUBREG_PROMOTED_UNSIGNED_P is only valid if SUBREG_PROMOTED_VAR_P, I'd hope that you don't need to care about what 0, 0 in those bits means, because everything should actually SUBREG_PROMOTED_UNSIGNED_SET around setting SUBREG_PROMOTED_VAR_P to non-zero. Jakub