[AArch64] PR82964: Fix 128-bit immediate ICEs
authorWilco Dijkstra <wdijkstr@arm.com>
Wed, 17 Jan 2018 16:31:42 +0000 (16:31 +0000)
committerWilco Dijkstra <wilco@gcc.gnu.org>
Wed, 17 Jan 2018 16:31:42 +0000 (16:31 +0000)
This fixes PR82964 which reports ICEs for some CONST_WIDE_INT immediates.
It turns out decimal floating point CONST_DOUBLE get changed into
CONST_WIDE_INT without checking the constraint on the operand, which
results in failures.  Avoid this by only allowing SF/DF/TF mode floating
point constants in aarch64_legitimate_constant_p.  A similar issue can
occur with 128-bit immediates which may be emitted even when disallowed
in aarch64_legitimate_constant_p, and the constraints in movti_aarch64
don't match.  Fix this with a new constraint and allowing valid immediates
in aarch64_legitimate_constant_p.

Rather than allowing all 128-bit immediates and expanding in up to 8
MOV/MOVK instructions, limit them to 4 instructions and use a literal
load for other cases.  Improve a few TImode tests to use a literal and
ensure they are skipped with -fpic.

This fixes all reported failures.

    gcc/
PR target/82964
* config/aarch64/aarch64.md (movti_aarch64): Use Uti constraint.
* config/aarch64/aarch64.c (aarch64_mov128_immediate): New function.
(aarch64_legitimate_constant_p): Just support CONST_DOUBLE
SF/DF/TF mode to avoid creating illegal CONST_WIDE_INT immediates.
* config/aarch64/aarch64-protos.h (aarch64_mov128_immediate):
Add declaration.
* config/aarch64/constraints.md (aarch64_movti_operand):
Limit immediates.
* config/aarch64/predicates.md (Uti): Add new constraint.

    gcc/testsuite/
PR target/79041
PR target/82964
* gcc.target/aarch64/pr79041-2.c: Improve test, disable with fpic.
* gcc.target/aarch64/pr78733.c: Improve test, disable with fpic.

Co-Authored-By: Richard Sandiford <richard.sandiford@linaro.org>
From-SVN: r256800

gcc/ChangeLog
gcc/config/aarch64/aarch64-protos.h
gcc/config/aarch64/aarch64.c
gcc/config/aarch64/aarch64.md
gcc/config/aarch64/constraints.md
gcc/config/aarch64/predicates.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/aarch64/pr78733.c
gcc/testsuite/gcc.target/aarch64/pr79041-2.c

index 53ed18decb76d8eb3e315e259227c35cd9c55326..85262662b49eb8304bbb58f5df35ff3c529e0bef 100644 (file)
@@ -1,3 +1,16 @@
+2018-01-17  Wilco Dijkstra  <wdijkstr@arm.com>
+           Richard Sandiford  <richard.sandiford@linaro.org>
+
+       * config/aarch64/aarch64.md (movti_aarch64): Use Uti constraint.
+       * config/aarch64/aarch64.c (aarch64_mov128_immediate): New function.
+       (aarch64_legitimate_constant_p): Just support CONST_DOUBLE 
+       SF/DF/TF mode to avoid creating illegal CONST_WIDE_INT immediates.
+       * config/aarch64/aarch64-protos.h (aarch64_mov128_immediate):
+       Add declaration.
+       * config/aarch64/constraints.md (aarch64_movti_operand):
+       Limit immediates.
+       * config/aarch64/predicates.md (Uti): Add new constraint.
+
 2018-01-17 Carl Love  <cel@us.ibm.com>
        * config/rs6000/vsx.md (define_expand xl_len_r,
        define_expand stxvl, define_expand *stxvl): Add match_dup argument.
index 2d705d2864760cae34da6d748bf37e41acd2ee00..ef1b0bc8e28582287c8141429644a5a40375c441 100644 (file)
@@ -475,6 +475,8 @@ void aarch64_split_128bit_move (rtx, rtx);
 
 bool aarch64_split_128bit_move_p (rtx, rtx);
 
+bool aarch64_mov128_immediate (rtx);
+
 void aarch64_split_simd_combine (rtx, rtx, rtx);
 
 void aarch64_split_simd_move (rtx, rtx);
index 2e70f3a2237aeed33560da0d0f38fe5634620517..17efac7a727bc1c5b16891af6af041faaf3116ef 100644 (file)
@@ -2393,6 +2393,24 @@ aarch64_internal_mov_immediate (rtx dest, rtx imm, bool generate,
   return num_insns;
 }
 
+/* Return whether imm is a 128-bit immediate which is simple enough to
+   expand inline.  */
+bool
+aarch64_mov128_immediate (rtx imm)
+{
+  if (GET_CODE (imm) == CONST_INT)
+    return true;
+
+  gcc_assert (CONST_WIDE_INT_NUNITS (imm) == 2);
+
+  rtx lo = GEN_INT (CONST_WIDE_INT_ELT (imm, 0));
+  rtx hi = GEN_INT (CONST_WIDE_INT_ELT (imm, 1));
+
+  return aarch64_internal_mov_immediate (NULL_RTX, lo, false, DImode)
+        + aarch64_internal_mov_immediate (NULL_RTX, hi, false, DImode) <= 4;
+}
+
+
 /* Return the number of temporary registers that aarch64_add_offset_1
    would need to add OFFSET to a register.  */
 
@@ -11738,7 +11756,10 @@ static bool
 aarch64_legitimate_constant_p (machine_mode mode, rtx x)
 {
   /* Support CSE and rematerialization of common constants.  */
-  if (CONST_INT_P (x) || CONST_DOUBLE_P (x) || GET_CODE (x) == CONST_VECTOR)
+  if (CONST_INT_P (x)
+      || (CONST_DOUBLE_P (x)
+         && (mode == SFmode || mode == DFmode || mode == TFmode))
+      || GET_CODE (x) == CONST_VECTOR)
     return true;
 
   /* Do not allow vector struct mode constants for Advanced SIMD.
@@ -11748,10 +11769,6 @@ aarch64_legitimate_constant_p (machine_mode mode, rtx x)
   if (vec_flags == (VEC_ADVSIMD | VEC_STRUCT))
     return false;
 
-  /* Do not allow wide int constants - this requires support in movti.  */
-  if (CONST_WIDE_INT_P (x))
-    return false;
-
   /* Only accept variable-length vector constants if they can be
      handled directly.
 
index edb6a7583338a924020d9f301aebc577f1fce63b..a6ecb391309494087416913c11f339cf10357977 100644 (file)
 
 (define_insn "*movti_aarch64"
   [(set (match_operand:TI 0
-        "nonimmediate_operand"  "=r, w,r,w,r,m,m,w,m")
+        "nonimmediate_operand"  "=   r,w, r,w,r,m,m,w,m")
        (match_operand:TI 1
-        "aarch64_movti_operand" " rn,r,w,w,m,r,Z,m,w"))]
+        "aarch64_movti_operand" " rUti,r, w,w,m,r,Z,m,w"))]
   "(register_operand (operands[0], TImode)
     || aarch64_reg_or_zero (operands[1], TImode))"
   "@
index 6cc4cadfd103313d9df75ac75005ee5c43f0be29..3eb07f11894a9223a007e6668d35cbb72012c3fa 100644 (file)
  (and (match_code "const_int")
       (match_test "aarch64_move_imm (ival, DImode)")))
 
+(define_constraint "Uti"
+ "A constant that can be used with a 128-bit MOV immediate operation."
+ (and (ior (match_code "const_int")
+          (match_code "const_wide_int"))
+      (match_test "aarch64_mov128_immediate (op)")))
+
 (define_constraint "UsO"
  "A constant that can be used with a 32-bit and operation."
  (and (match_code "const_int")
index 0df1a4d324c329848cbb447372dc7712eb34840e..159e74a1ed737c49063620564c2125215c37a4b6 100644 (file)
            (match_test "aarch64_mov_operand_p (op, mode)"))))
 
 (define_predicate "aarch64_movti_operand"
-  (and (match_code "reg,subreg,mem,const_int")
-       (ior (match_operand 0 "register_operand")
-           (ior (match_operand 0 "memory_operand")
-                (match_operand 0 "const_int_operand")))))
+  (ior (match_operand 0 "register_operand")
+       (match_operand 0 "memory_operand")
+       (and (match_operand 0 "const_scalar_int_operand")
+           (match_test "aarch64_mov128_immediate (op)"))))
 
 (define_predicate "aarch64_reg_or_imm"
-  (and (match_code "reg,subreg,const_int")
-       (ior (match_operand 0 "register_operand")
-           (match_operand 0 "const_int_operand"))))
+  (ior (match_operand 0 "register_operand")
+       (match_operand 0 "const_scalar_int_operand")))
 
 ;; True for integer comparisons and for FP comparisons other than LTGT or UNEQ.
 (define_special_predicate "aarch64_comparison_operator"
index 0fd9f9944b7903ee1dc77c28efb97a0e1bcebf3d..f51f41710c686986d414896e782295581493f16f 100644 (file)
@@ -1,3 +1,11 @@
+2018-01-17  Wilco Dijkstra  <wdijkstr@arm.com>
+           Richard Sandiford  <richard.sandiford@linaro.org>
+
+       PR target/79041
+       PR target/82964
+       * gcc.target/aarch64/pr79041-2.c: Improve test, disable with fpic.
+       * gcc.target/aarch64/pr78733.c: Improve test, disable with fpic.
+
 2018-01-17  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        * lib/target-supports.exp: Fix -march arguments in arm arch effective
index ce462cedf9f049feb03addfb010b2f339972c337..4695b5c1b2b7c9b515995e242dd38e0519a48a2b 100644 (file)
@@ -1,10 +1,13 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -mpc-relative-literal-loads" } */
+/* { dg-options "-O2 -mcmodel=large -mpc-relative-literal-loads" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-skip-if "-mcmodel=large, no support for -fpic" { aarch64-*-* }  { "-fpic" } { "" } } */
 
 __int128
 t (void)
 {
-  return (__int128)1 << 80;
+  return ((__int128)0x123456789abcdef << 64) | 0xfedcba987654321;
 }
 
 /* { dg-final { scan-assembler "adr" } } */
+/* { dg-final { scan-assembler-not "adrp" } } */
index a889dfdd89549fdd19d2e167d43835ff0cbb236a..4695b5c1b2b7c9b515995e242dd38e0519a48a2b 100644 (file)
@@ -1,11 +1,12 @@
 /* { dg-do compile } */
 /* { dg-options "-O2 -mcmodel=large -mpc-relative-literal-loads" } */
 /* { dg-require-effective-target lp64 } */
+/* { dg-skip-if "-mcmodel=large, no support for -fpic" { aarch64-*-* }  { "-fpic" } { "" } } */
 
 __int128
 t (void)
 {
-  return (__int128)1 << 80;
+  return ((__int128)0x123456789abcdef << 64) | 0xfedcba987654321;
 }
 
 /* { dg-final { scan-assembler "adr" } } */