This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH][GCC][ARM] Fix can_change_mode_class for big-endian


Hi Tamar,

On 19/06/18 15:14, Tamar Christina wrote:
Hi All,

This patch requires https://gcc.gnu.org/ml/gcc-patches/2018-06/msg01145.html to work,
it has been accepted once already but caused a regression on certain configuratoins.
I am re-submitting it with the required mid-end change and requesting a back-port.

--- original patch.

Taking the subreg of a vector mode on big-endian may result in an infinite
recursion and eventually a segfault once we run out of stack space.

As an example, taking a subreg of V4HF to SImode we end up in the following
loop on big-endian:

#861 0x00000000008462e9 in operand_subword_force src/gcc/gcc/emit-rtl.c:1787
#862 0x0000000000882a90 in emit_move_multi_word src/gcc/gcc/expr.c:3621
#863 0x000000000087eea1 in emit_move_insn_1 src/gcc/gcc/expr.c:3698
#864 0x000000000087f350 in emit_move_insn src/gcc/gcc/expr.c:3757
#865 0x000000000085e326 in copy_to_reg src/gcc/gcc/explow.c:603
#866 0x00000000008462e9 in operand_subword_force src/gcc/gcc/emit-rtl.c:1787

The reason is that operand_subword_force will always fail. When the value is in
a register that can't be accessed as a multi word the code tries to create a new
psuedo register and emit the value to it. Eventually you end up in simplify_gen_subreg
which calls validate_subreg.

validate_subreg will however always fail because of the REG_CAN_CHANGE_MODE_P check.

On little endian this check always returns true. On big-endian this check is supposed
to prevent values that have a size larger than word size, due to those being stored in
VFP registers.

However we are only interested in a subreg of the vector mode, so we should be checking
the unit size, not the size of the entire mode. Doing this fixes the problem.

Regtested on armeb-none-eabi and no regressions.
Bootstrapped on arm-none-linux-gnueabihf and no issues.

Ok for trunk? and for backport to GCC 8?

Thanks,
Tamar

gcc/
2018-06-19  Tamar Christina  <tamar.christina@arm.com>

        PR target/84711
        * config/arm/arm.c (arm_can_change_mode_class): Use GET_MODE_UNIT_SIZE
        instead of GET_MODE_SIZE when comparing Units.

gcc/testsuite/
2018-06-19  Tamar Christina  <tamar.christina@arm.com>

        PR target/84711
        * gcc.target/arm/big-endian-subreg.c: New.

--


diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 90d62e699bce9594879be2e3016c9b36c7e064c8..703632240822e762a906570964b949c783df56f3 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -31508,8 +31508,8 @@ arm_can_change_mode_class (machine_mode from, machine_mode to,
 {
   if (TARGET_BIG_END
       && !(GET_MODE_SIZE (from) == 16 && GET_MODE_SIZE (to) == 8)
-      && (GET_MODE_SIZE (from) > UNITS_PER_WORD
-	  || GET_MODE_SIZE (to) > UNITS_PER_WORD)
+      && (GET_MODE_UNIT_SIZE (from) > UNITS_PER_WORD
+	  || GET_MODE_UNIT_SIZE (to) > UNITS_PER_WORD)

Does GET_MODE_UNIT_SIZE do what you want? Its documentation in rtl.texi says:
"Returns the size in bytes of the subunits of a datum of mode @var{m}.
 This is the same as @code{GET_MODE_SIZE} except in the case of complex
 modes.  For them, the unit size is the size of the real or imaginary
 part."

Does it also do the right thing for vector modes (GET_MODE_SIZE (GET_MODE_INNER (mode))) ?
If so, this patch is ok, but we'll need to update the documentation to make it more explicit.

Thanks for the patch,
Kyrill




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]