From c0bb5bc54feab4bac0df04f358ec9e839a32b2a2 Mon Sep 17 00:00:00 2001 From: Wilco Dijkstra Date: Wed, 17 Jan 2018 16:31:42 +0000 Subject: [PATCH] [AArch64] PR82964: Fix 128-bit immediate ICEs 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 From-SVN: r256800 --- gcc/ChangeLog | 13 ++++++++++ gcc/config/aarch64/aarch64-protos.h | 2 ++ gcc/config/aarch64/aarch64.c | 27 ++++++++++++++++---- gcc/config/aarch64/aarch64.md | 4 +-- gcc/config/aarch64/constraints.md | 6 +++++ gcc/config/aarch64/predicates.md | 13 +++++----- gcc/testsuite/ChangeLog | 8 ++++++ gcc/testsuite/gcc.target/aarch64/pr78733.c | 7 +++-- gcc/testsuite/gcc.target/aarch64/pr79041-2.c | 3 ++- 9 files changed, 66 insertions(+), 17 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 53ed18decb7..85262662b49 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2018-01-17 Wilco Dijkstra + Richard Sandiford + + * 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 * config/rs6000/vsx.md (define_expand xl_len_r, define_expand stxvl, define_expand *stxvl): Add match_dup argument. diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index 2d705d28647..ef1b0bc8e28 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -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); diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 2e70f3a2237..17efac7a727 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -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. diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index edb6a758333..a6ecb391309 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -1079,9 +1079,9 @@ (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))" "@ diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md index 6cc4cadfd10..3eb07f11894 100644 --- a/gcc/config/aarch64/constraints.md +++ b/gcc/config/aarch64/constraints.md @@ -87,6 +87,12 @@ (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") diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md index 0df1a4d324c..159e74a1ed7 100644 --- a/gcc/config/aarch64/predicates.md +++ b/gcc/config/aarch64/predicates.md @@ -293,15 +293,14 @@ (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" diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0fd9f9944b7..f51f41710c6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2018-01-17 Wilco Dijkstra + Richard Sandiford + + 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 * lib/target-supports.exp: Fix -march arguments in arm arch effective diff --git a/gcc/testsuite/gcc.target/aarch64/pr78733.c b/gcc/testsuite/gcc.target/aarch64/pr78733.c index ce462cedf9f..4695b5c1b2b 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr78733.c +++ b/gcc/testsuite/gcc.target/aarch64/pr78733.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/pr79041-2.c b/gcc/testsuite/gcc.target/aarch64/pr79041-2.c index a889dfdd895..4695b5c1b2b 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr79041-2.c +++ b/gcc/testsuite/gcc.target/aarch64/pr79041-2.c @@ -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" } } */ -- 2.30.2