https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65932

--- Comment #17 from Jim Wilson <wilson at gcc dot gnu.org> ---
I've been researching how the ARM PROMOTE_MODE reached its current state. 
There are a number of issues here.

1) There is a comment that says zero extension is faster for char than signed
extension.  This is only true before the [su]xtb instructions were added, i.e.
!arm_arch6.  Before these instructions, zero extend can be done with an and
immediate, but sign extension requires two shifts.  So there is no benefit to
zero extension for current architectures.

2) The comment doesn't apply to shorts, which require two shifts for both zero
and sign extension when !arm_arch6.  The signedness was changed for shorts
originally because some processors did not support unaligned accesses, and had
to loads shorts with two load byte instructions.  This required 3 insns for
zero extend and 4 for sign extend, so there was an advantage to zero extension,
but only if the processor did not support unaligned accesses.  Unfortunately,
the support was flawed, and did
        UNSIGNEDP = TARGET_MMU_TRAPS != 0;      \
which forces it to unsigned for MMU_TRAPS and signed for the default case.  It
should have been something like
        if (TARGET_MMU_TRAPS) UNSIGNEDP = 1; \
When the TARGET_MMU_TRAPS feature was removed, this code was changed to set
UNSIGNEDP to 0 unconditionally, which compounded the error.  This code should
have been removed when the TARGET_MMU_TRAPS feature was removed.

3) Originally PROMOTE_FUNCTION_ARGS was a boolean that indicated whether
PROMOTE_MODE applied to function arguments or not.  When it was changed to a
hook, it was made into a function.  So now we have two sets of similar code,
one in PROMOTE_MODE and one in arm_promote_function_mode
(TARGET_PROMOTE_FUNCTION_MODE).  The two sets of code should be identical, but
the unsigned-ness changing was left out of the arm_promote_function_mode code. 
The result is that we have two different in-register representations for signed
char/short symbols, one form for parameters and one form for local variables. 
This inconsistency is confusing the out-of-ssa pass.  Since changing
arm_promote_function_mode is effectively an ABI change, it is safer to change
PROMOTE_MODE to match.

4) There is a general principle that you should not change signedness in
PROMOTE_MODE unless the hardware forces you to do so.  For instance, for the
MIPS64 target, the hardware requires that all 32-bit values in 64-bit registers
be sign-extended, and 32-bit instructions may trap if this is not true.  Thus
the mips port forces all 32-bit values to be signed.  But the arm architecture
has no similar constraint, and hence we should not be changing signedness here.
 Changing signedness results in less efficient code, as can be seen in this
testcase, where the compiler must emit both a zero-extend and a sign-extend in
the loop.  The sign-extend is required to get correct results for a compare,
and the zero-extend is required because PROMOTE_MODE requires it.

Reply via email to