On 03/03/15 17:59, Kyrylo Tkachov wrote:


-----Original Message-----
From: Kyrylo Tkachov
Sent: 27 February 2015 14:30
To: Kyrylo Tkachov; GCC Patches
Cc: Ramana Radhakrishnan; Richard Earnshaw
Subject: RE: [PATCH][ARM] PR target/64600 Fix another ICE with -
mtune=xscale: properly sign-extend mask during constant splitting

On 03/02/15 15:18, Kyrill Tkachov wrote:
Hi all,

The ICE in this PR occurs when -mtune=xscale triggers a particular
path through arm_gen_constant during expand that creates a 0xfffff00f
mask but for a 64-bit HOST_WIDE_INT doesn't sign extend it into
0xfffffffffffff00f that signifies the required -4081. It leaves it as
0xfffff00f (4294963215) that breaks when later combine tries to
perform an SImode bitwise AND using the wide-int machinery.

I think the correct approach here is to use trunc_int_for_mode that
correctly sign-extends the constant so that it is properly represented
by a HOST_WIDE_INT for the required mode.

Bootstrapped and tested arm-none-linux-gnueabihf with -mtune=xscale in
BOOT_CFLAGS.

The testcase triggers for -mcpu=xscale and all slowmul targets because
they are the only ones that have the constant_limit tune parameter set
to anything >1 which is required to follow this particular path
through arm_split_constant. Also, the rtx costs can hide this ICE
sometimes.

Ok for trunk?

Thanks,
Kyrill

2015-02-03  Kyrylo Tkachov  <kyrylo.tkac...@arm.com>

      PR target/64600
      * config/arm/arm.c (arm_gen_constant, AND case): Call
      trunc_int_for_mode when constructing AND mask.

2015-02-03  Kyrylo Tkachov  <kyrylo.tkac...@arm.com>

      PR target/64600
      * gcc.target/arm/pr64600_1.c: New test.
arm-xscale-wide.patch
commit 52388a359dd65276bccfac499a2fd9e406fbe1a8
Author: Kyrylo Tkachov <kyrylo.tkac...@arm.com>
Date:   Tue Jan 20 11:21:34 2015 +0000

     [ARM] Fix ICE due to arm_gen_constant not sign_extending

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index
db4834b..d0f3a52 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -4709,19 +4709,20 @@ arm_gen_constant (enum rtx_code code,
machine_mode mode, rtx cond,

          if ((remainder | shift_mask) != 0xffffffff)
            {
+             HOST_WIDE_INT new_val
+               = trunc_int_for_mode (remainder | shift_mask, mode);

Offlist, Richard mentioned that trunc_int_for_mode may pessimize codegen
for HImode values due to excessive setting of bits and using
ARM_SIGN_EXTEND might be preferable.
I've tried that and it does fix the ICE and goes through testing ok. Bootstrap
still ongoing.
I didn't perform any code quality investigation. Richard, are there any
particular code sequences  that you'd like us to investigate here?


Here's the alternative version using ARM_SIGN_EXTEND if you want to have  a 
look.
Thanks,
Kyrill


2015-03-03  Kyrylo Tkachov  <kyrylo.tkac...@arm.com>

        PR target/64600
        * config/arm/arm.c (arm_gen_constant, AND case): Use
        ARM_SIGN_EXTEND when constructing AND mask.

2015-03-03  Kyrylo Tkachov  <kyrylo.tkac...@arm.com>

        PR target/64600
        * gcc.target/arm/pr64600_1.c: New test.

Thanks,
Kyrill


This is OK. Let's take the ARM_SIGN_EXTEND version instead of the other one given what Richard says.


regards
Ramana



+
              if (generate)
                {
                  rtx new_src = subtargets ? gen_reg_rtx (mode) : target;
-                 insns = arm_gen_constant (AND, mode, cond,
-                                           remainder | shift_mask,
+                 insns = arm_gen_constant (AND, SImode, cond, new_val,
                                            new_src, source, subtargets, 1);
                  source = new_src;
                }
              else
                {
                  rtx targ = subtargets ? NULL_RTX : target;
-                 insns = arm_gen_constant (AND, mode, cond,
-                                           remainder | shift_mask,
+                 insns = arm_gen_constant (AND, mode, cond, new_val,
                                            targ, source, subtargets, 0);
                }
            }
@@ -4744,12 +4745,13 @@ arm_gen_constant (enum rtx_code code,
machine_mode mode, rtx cond,

          if ((remainder | shift_mask) != 0xffffffff)
            {
+             HOST_WIDE_INT new_val
+               = trunc_int_for_mode (remainder | shift_mask, mode);
              if (generate)
                {
                  rtx new_src = subtargets ? gen_reg_rtx (mode) : target;

-                 insns = arm_gen_constant (AND, mode, cond,
-                                           remainder | shift_mask,
+                 insns = arm_gen_constant (AND, mode, cond, new_val,
                                            new_src, source, subtargets, 1);
                  source = new_src;
                }
@@ -4757,8 +4759,7 @@ arm_gen_constant (enum rtx_code code,
machine_mode mode, rtx cond,
                {
                  rtx targ = subtargets ? NULL_RTX : target;

-                 insns = arm_gen_constant (AND, mode, cond,
-                                           remainder | shift_mask,
+                 insns = arm_gen_constant (AND, mode, cond, new_val,
                                            targ, source, subtargets, 0);
                }
            }
diff --git a/gcc/testsuite/gcc.target/arm/pr64600_1.c
b/gcc/testsuite/gcc.target/arm/pr64600_1.c
new file mode 100644
index 0000000..6ba3fa2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr64600_1.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mtune=xscale" } */
+
+typedef unsigned int speed_t;
+typedef unsigned int tcflag_t;
+
+struct termios {
+ tcflag_t c_cflag;
+};
+
+speed_t
+cfgetospeed (const struct termios *tp) {
+  return tp->c_cflag & 010017;
+}


Reply via email to