[PATCH][2 of 2] RTL expansion for zero sign extension elimination with VRP
Eric Botcazou
ebotcazou@adacore.com
Mon Jul 1 09:22:00 GMT 2013
[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 <kuganv@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
More information about the Gcc-patches
mailing list