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]

[PATCH][ARM] PR target/79145 Fix xordi3 expander for immediate operands in iWMMXt


Hi all,

We're hitting an ICE when expanding a DImode xor with an immediate on TARGET_IWMMXT:
(insn 6 5 7 2 (set (reg:DI 111 [ t1.1_3 ])
        (xor:DI (reg:DI 110 [ t1.0_2 ])
            (const_int 85 [0x55]))) ./z32.c:13 -1
     (nil))

The problem is that the general xordi3 expander accepts some immediates in operand 2 but the iwmmxt_xordi3
define_insn only accepts register operands, and nothing forces the operand into a register in between.
This doesn't affect the iordi3 or anddi3 expanders because their predicates are designed to accept immediates
valid for the VORR and VBIC NEON instructions and thus check for TARGET_NEON as well, so they don't accept any
immediates during expand time for TARGET_IWMMXT.

A fix could be to modify arm_xordi_operand to allow only register operands for TARGET_IWMMXT.
Another approach, used in this patch, is to force the constants into registers in the expander itself.

Bootstrapped and tested on arm-none-linux-gnueabihf (I don't have access to iWMMXt hardware).

Ok for trunk and the branches after some time?
This patch should only affect TARGET_IWMMXT and therefore is pretty safe at any stage.

Thanks,
Kyrill

2016-01-25  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

    PR target/79145
    * config/arm/arm.md (xordi3): Force constant operand into a register
    for TARGET_IWMMXT.

2016-01-25  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

    PR target/79145
    * gcc.target/arm/pr79145.c: New test.
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 2eee8bc5701297f52e5ed991f074f1069bde1b6e..48bf07e5b6c121944b38ab8d0d14b029d2b34560 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -3328,7 +3328,14 @@ (define_expand "xordi3"
 	(xor:DI (match_operand:DI 1 "s_register_operand" "")
 		(match_operand:DI 2 "arm_xordi_operand" "")))]
   "TARGET_32BIT"
-  ""
+  {
+    /* The iWMMXt pattern for xordi3 accepts only register operands but we want
+       to reuse this expander for all TARGET_32BIT targets so just force the
+       constants into a register.  Unlike for the anddi3 and iordi3 there are
+       no NEON instructions that take an immediate.  */
+    if (TARGET_IWMMXT && !REG_P (operands[2]))
+      operands[2] = force_reg (DImode, operands[2]);
+  }
 )
 
 (define_insn_and_split "*xordi3_insn"
diff --git a/gcc/testsuite/gcc.target/arm/pr79145.c b/gcc/testsuite/gcc.target/arm/pr79145.c
new file mode 100644
index 0000000000000000000000000000000000000000..667824400390d6fe72d05a85769d210791b8c378
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr79145.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-skip-if "Test is specific to the iWMMXt" { arm*-*-* } { "-mcpu=*" } { "-mcpu=iwmmxt" } } */
+/* { dg-skip-if "Test is specific to the iWMMXt" { arm*-*-* } { "-mabi=*" } { "-mabi=iwmmxt" } } */
+/* { dg-skip-if "Test is specific to the iWMMXt" { arm*-*-* } { "-march=*" } { "-march=iwmmxt" } } */
+/* { dg-skip-if "Test is specific to ARM mode" { arm*-*-* } { "-mthumb" } { "" } } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-require-effective-target arm_iwmmxt_ok } */
+/* { dg-options "-mcpu=iwmmxt" } */
+
+int
+main (void)
+{
+  volatile long long t1;
+  t1 ^= 0x55;
+  return 0;
+}

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