[Sorry for the delay] > For example, when an expression is evaluated and it's value is assigned > to variable of type short, the generated RTL would look something like > the following. > > (set (reg:SI 110) > (zero_extend:SI (subreg:HI (reg:SI 117) 0))) > > However, if during value range propagation, if we can say for certain > that the value of the expression which is present in register 117 is > within the limits of short and there is no sign conversion, we do not > need to perform the subreg and zero_extend; instead we can generate the > following RTl. > > (set (reg:SI 110) > (reg:SI 117))) > > Same could be done for other assign statements.
The idea looks interesting. Some remarks: > +2013-06-03 Kugan Vivekanandarajah <kug...@linaro.org> > + > + * gcc/dojump.c (do_compare_and_jump): generates rtl without > + zero/sign extension if redundant. > + * gcc/cfgexpand.c (expand_gimple_stmt_1): Likewise. > + * gcc/gimple.c (gimple_assign_is_zero_sign_ext_redundant) : New > + function. > + * gcc/gimple.h (gimple_assign_is_zero_sign_ext_redundant) : New > + function definition. No gcc/ prefix in entries for gcc/ChangeLog. "Generate RTL without..." + /* If the value in SUBREG of temp fits that SUBREG (does not + overflow) and is assigned to target SUBREG of the same mode + without sign convertion, we can skip the SUBREG + and extension. */ + else if (promoted + && gimple_assign_is_zero_sign_ext_redundant (stmt) + && (GET_CODE (temp) == SUBREG) + && (GET_MODE (target) == GET_MODE (temp)) + && (GET_MODE (SUBREG_REG (target)) + == GET_MODE (SUBREG_REG (temp)))) + emit_move_insn (SUBREG_REG (target), SUBREG_REG (temp)); else if (promoted) { int unsignedp = SUBREG_PROMOTED_UNSIGNED_P (target); Can we relax the strict mode equality here? This change augments the same transformation applied to the RHS when it is also a SUBREG_PROMOTED_VAR_P at the beginning of convert_move, but the condition on the mode is less strict in the latter case, so maybe it can serve as a model here. + /* Is zero/sign extension redundant as per VRP. */ + bool op0_ext_redundant = false; + bool op1_ext_redundant = false; + + /* If promoted and the value in SUBREG of op0 fits (does not overflow), + it is a candidate for extension elimination. */ + if (GET_CODE (op0) == SUBREG && SUBREG_PROMOTED_VAR_P (op0)) + op0_ext_redundant = + gimple_assign_is_zero_sign_ext_redundant (SSA_NAME_DEF_STMT (treeop0)); + + /* If promoted and the value in SUBREG of op1 fits (does not overflow), + it is a candidate for extension elimination. */ + if (GET_CODE (op1) == SUBREG && SUBREG_PROMOTED_VAR_P (op1)) + op1_ext_redundant = + gimple_assign_is_zero_sign_ext_redundant (SSA_NAME_DEF_STMT (treeop1)); Are the gimple_assign_is_zero_sign_ext_redundant checks necessary here? When set on a SUBREG, SUBREG_PROMOTED_VAR_P guarantees that SUBREG_REG is always properly extended (otherwise it's a bug) so don't you just need to compare SUBREG_PROMOTED_UNSIGNED_SET? See do_jump for an existing case. + /* If zero/sign extension is redundant, generate RTL + for operands without zero/sign extension. */ + if ((op0_ext_redundant || TREE_CODE (treeop0) == INTEGER_CST) + && (op1_ext_redundant || TREE_CODE (treeop1) == INTEGER_CST)) Don't you need to be careful with the INTEGER_CSTs here? The CONST_INTs are always sign-extended in RTL so 0x80 is always represented by (const_int -128) in QImode, whatever the signedness. If SUBREG_PROMOTED_UNSIGNED_SET is true, then comparing in QImode and comparing in e.g. SImode wouldn't be equivalent. -- Eric Botcazou