Hi there,
The "*neon_mov<mode>" patterns for 128 bit sized quantities uses the "Dn" constraint to match vmov.f32 and vmov.i<vec-width> patterns. This constraint boils down to using the `neon_immediate_valid` function. Once the constraint has matched, the output C statement asserts that function passes. The output C statement calls `neon_immediate_valid` with the mode taken from the iterator, while the constraint takes the mode from the operand. This can cause a discrepency when the operand is a CONST_INT, as the constraint passes VOIDmode which `neon_immediate_valid` treats as DImode, while the C statement passes the mode of the iterator which can be TImode. When this happens, the `neon_immediate_valid` can fail in the second call (if e.g. the CONST_INT is a valid immediate in DImode but not TImode) which would trigger the assertion. The testcase added with this patch triggers this when compiled with an arm cross compiler using the command line below. gcc -march=armv8-a -c neon-immediate-timode.c -O1 -mfloat-abi=hard -mfpu=neon-fp-armv8 This patch splits the original "Dn" constraint into three new constraints, "DN" for TImode CONST_INT, "Dn" for DImode CONST_INT, and "Dm" for CONST_VECTOR. Splitting things up this way requires using one extra alternative in the "*neon_mov<mode>" patterns, but makes it clear from the constraint what mode is being used. We also remove the behaviour of treating VOIDmode as DImode in `neon_valid_immediate` since the original "Dn" constraint was the only place that functionality was used. VOIDmode is now never passed to that function. An assertion has been added to the function to ensure this problem is caught earlier on. Bootstrapped on arm-none-linux-gnueabihf Regtested on cross-compiler arm-none-eabi gcc/ChangeLog: 2019-04-09 Matthew Malcomson <matthew.malcomson@arm.com> PR target/90024 * config/arm/arm.c (neon_valid_immediate): Disallow VOIDmode parameter. * config/arm/constraints.md (Dm, DN, Dn): Split previous Dn constraint into three. * config/arm/neon.md (*neon_mov<mode>): Account for TImode and DImode differences directly. (*smax<mode>3_neon, vashl<mode>3, vashr<mode>3_imm): Use Dm constraint. gcc/testsuite/ChangeLog: 2019-04-09 Matthew Malcomson <matthew.malcomson@arm.com> PR target/90024 * gcc.dg/torture/neon-immediate-timode.c: New test. From-SVN: r270226
This commit is contained in:
parent
765f8786cf
commit
e009dfb320
@ -1,3 +1,13 @@
|
||||
2019-04-09 Matthew Malcomson <matthew.malcomson@arm.com>
|
||||
|
||||
PR target/90024
|
||||
* config/arm/arm.c (neon_valid_immediate): Disallow VOIDmode parameter.
|
||||
* config/arm/constraints.md (Dm, DN, Dn): Split previous Dn constraint
|
||||
into three.
|
||||
* config/arm/neon.md (*neon_mov<mode>): Account for TImode and DImode
|
||||
differences directly.
|
||||
(*smax<mode>3_neon, vashl<mode>3, vashr<mode>3_imm): Use Dm constraint.
|
||||
|
||||
2019-04-09 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR translation/90011
|
||||
|
@ -11998,8 +11998,7 @@ neon_valid_immediate (rtx op, machine_mode mode, int inverse,
|
||||
else
|
||||
{
|
||||
n_elts = 1;
|
||||
if (mode == VOIDmode)
|
||||
mode = DImode;
|
||||
gcc_assert (mode != VOIDmode);
|
||||
}
|
||||
|
||||
innersize = GET_MODE_UNIT_SIZE (mode);
|
||||
|
@ -31,8 +31,8 @@
|
||||
;; 'H' was previously used for FPA.
|
||||
|
||||
;; The following multi-letter normal constraints have been used:
|
||||
;; in ARM/Thumb-2 state: Da, Db, Dc, Dd, Dn, Dl, DL, Do, Dv, Dy, Di, Dt, Dp,
|
||||
;; Dz, Tu
|
||||
;; in ARM/Thumb-2 state: Da, Db, Dc, Dd, Dn, DN, Dm, Dl, DL, Do, Dv, Dy, Di,
|
||||
;; Dt, Dp, Dz, Tu
|
||||
;; in Thumb-1 state: Pa, Pb, Pc, Pd, Pe
|
||||
;; in Thumb-2 state: Ha, Pj, PJ, Ps, Pt, Pu, Pv, Pw, Px, Py, Pz
|
||||
;; in all states: Pf
|
||||
@ -298,14 +298,28 @@
|
||||
(and (match_code "const_double,const_int")
|
||||
(match_test "TARGET_32BIT && arm_const_double_by_immediates (op)")))
|
||||
|
||||
(define_constraint "Dn"
|
||||
(define_constraint "Dm"
|
||||
"@internal
|
||||
In ARM/Thumb-2 state a const_vector or const_int which can be loaded with a
|
||||
Neon vmov immediate instruction."
|
||||
(and (match_code "const_vector,const_int")
|
||||
In ARM/Thumb-2 state a const_vector which can be loaded with a Neon vmov
|
||||
immediate instruction."
|
||||
(and (match_code "const_vector")
|
||||
(match_test "TARGET_32BIT
|
||||
&& imm_for_neon_mov_operand (op, GET_MODE (op))")))
|
||||
|
||||
(define_constraint "Dn"
|
||||
"@internal
|
||||
In ARM/Thumb-2 state a DImode const_int which can be loaded with a Neon vmov
|
||||
immediate instruction."
|
||||
(and (match_code "const_int")
|
||||
(match_test "TARGET_32BIT && imm_for_neon_mov_operand (op, DImode)")))
|
||||
|
||||
(define_constraint "DN"
|
||||
"@internal
|
||||
In ARM/Thumb-2 state a TImode const_int which can be loaded with a Neon vmov
|
||||
immediate instruction."
|
||||
(and (match_code "const_int")
|
||||
(match_test "TARGET_32BIT && imm_for_neon_mov_operand (op, TImode)")))
|
||||
|
||||
(define_constraint "Dl"
|
||||
"@internal
|
||||
In ARM/Thumb-2 state a const_vector which can be used with a Neon vorr or
|
||||
|
@ -25,14 +25,14 @@
|
||||
|
||||
(define_insn "*neon_mov<mode>"
|
||||
[(set (match_operand:VDX 0 "nonimmediate_operand"
|
||||
"=w,Un,w, w, ?r,?w,?r, ?Us,*r")
|
||||
"=w,Un,w, w, w, ?r,?w,?r, ?Us,*r")
|
||||
(match_operand:VDX 1 "general_operand"
|
||||
" w,w, Dn,Uni, w, r, Usi,r,*r"))]
|
||||
" w,w, Dm,Dn,Uni, w, r, Usi,r,*r"))]
|
||||
"TARGET_NEON
|
||||
&& (register_operand (operands[0], <MODE>mode)
|
||||
|| register_operand (operands[1], <MODE>mode))"
|
||||
{
|
||||
if (which_alternative == 2)
|
||||
if (which_alternative == 2 || which_alternative == 3)
|
||||
{
|
||||
int width, is_valid;
|
||||
static char templ[40];
|
||||
@ -53,32 +53,33 @@
|
||||
switch (which_alternative)
|
||||
{
|
||||
case 0: return "vmov\t%P0, %P1 @ <mode>";
|
||||
case 1: case 3: return output_move_neon (operands);
|
||||
case 2: gcc_unreachable ();
|
||||
case 4: return "vmov\t%Q0, %R0, %P1 @ <mode>";
|
||||
case 5: return "vmov\t%P0, %Q1, %R1 @ <mode>";
|
||||
case 8: return "#";
|
||||
case 1: case 4: return output_move_neon (operands);
|
||||
case 2: case 3: gcc_unreachable ();
|
||||
case 5: return "vmov\t%Q0, %R0, %P1 @ <mode>";
|
||||
case 6: return "vmov\t%P0, %Q1, %R1 @ <mode>";
|
||||
case 9: return "#";
|
||||
default: return output_move_double (operands, true, NULL);
|
||||
}
|
||||
}
|
||||
[(set_attr "type" "neon_move<q>,neon_store1_1reg,neon_move<q>,\
|
||||
neon_load1_1reg, neon_to_gp<q>,neon_from_gp<q>,\
|
||||
neon_load1_2reg, neon_store1_2reg, multiple")
|
||||
(set_attr "length" "4,4,4,4,4,4,8,8,8")
|
||||
(set_attr "arm_pool_range" "*,*,*,1020,*,*,1020,*,*")
|
||||
(set_attr "thumb2_pool_range" "*,*,*,1018,*,*,1018,*,*")
|
||||
(set_attr "neg_pool_range" "*,*,*,1004,*,*,1004,*,*")])
|
||||
neon_move<q>,neon_load1_1reg, neon_to_gp<q>,\
|
||||
neon_from_gp<q>,neon_load1_2reg, neon_store1_2reg,\
|
||||
multiple")
|
||||
(set_attr "length" "4,4,4,4,4,4,4,8,8,8")
|
||||
(set_attr "arm_pool_range" "*,*,*,*,1020,*,*,1020,*,*")
|
||||
(set_attr "thumb2_pool_range" "*,*,*,*,1018,*,*,1018,*,*")
|
||||
(set_attr "neg_pool_range" "*,*,*,*,1004,*,*,1004,*,*")])
|
||||
|
||||
(define_insn "*neon_mov<mode>"
|
||||
[(set (match_operand:VQXMOV 0 "nonimmediate_operand"
|
||||
"=w,Un,w, w, ?r,?w,?r,?r, ?Us")
|
||||
"=w,Un,w, w, w, ?r,?w,?r,?r, ?Us")
|
||||
(match_operand:VQXMOV 1 "general_operand"
|
||||
" w,w, Dn,Uni, w, r, r, Usi, r"))]
|
||||
" w,w, Dm,DN,Uni, w, r, r, Usi, r"))]
|
||||
"TARGET_NEON
|
||||
&& (register_operand (operands[0], <MODE>mode)
|
||||
|| register_operand (operands[1], <MODE>mode))"
|
||||
{
|
||||
if (which_alternative == 2)
|
||||
if (which_alternative == 2 || which_alternative == 3)
|
||||
{
|
||||
int width, is_valid;
|
||||
static char templ[40];
|
||||
@ -99,20 +100,20 @@
|
||||
switch (which_alternative)
|
||||
{
|
||||
case 0: return "vmov\t%q0, %q1 @ <mode>";
|
||||
case 1: case 3: return output_move_neon (operands);
|
||||
case 2: gcc_unreachable ();
|
||||
case 4: return "vmov\t%Q0, %R0, %e1 @ <mode>\;vmov\t%J0, %K0, %f1";
|
||||
case 5: return "vmov\t%e0, %Q1, %R1 @ <mode>\;vmov\t%f0, %J1, %K1";
|
||||
case 1: case 4: return output_move_neon (operands);
|
||||
case 2: case 3: gcc_unreachable ();
|
||||
case 5: return "vmov\t%Q0, %R0, %e1 @ <mode>\;vmov\t%J0, %K0, %f1";
|
||||
case 6: return "vmov\t%e0, %Q1, %R1 @ <mode>\;vmov\t%f0, %J1, %K1";
|
||||
default: return output_move_quad (operands);
|
||||
}
|
||||
}
|
||||
[(set_attr "type" "neon_move_q,neon_store2_2reg_q,neon_move_q,\
|
||||
neon_load2_2reg_q,neon_to_gp_q,neon_from_gp_q,\
|
||||
mov_reg,neon_load1_4reg,neon_store1_4reg")
|
||||
(set_attr "length" "4,8,4,8,8,8,16,8,16")
|
||||
(set_attr "arm_pool_range" "*,*,*,1020,*,*,*,1020,*")
|
||||
(set_attr "thumb2_pool_range" "*,*,*,1018,*,*,*,1018,*")
|
||||
(set_attr "neg_pool_range" "*,*,*,996,*,*,*,996,*")])
|
||||
neon_move_q,neon_load2_2reg_q,neon_to_gp_q,\
|
||||
neon_from_gp_q,mov_reg,neon_load1_4reg,neon_store1_4reg")
|
||||
(set_attr "length" "4,8,4,4,8,8,8,16,8,16")
|
||||
(set_attr "arm_pool_range" "*,*,*,*,1020,*,*,*,1020,*")
|
||||
(set_attr "thumb2_pool_range" "*,*,*,*,1018,*,*,*,1018,*")
|
||||
(set_attr "neg_pool_range" "*,*,*,*,996,*,*,*,996,*")])
|
||||
|
||||
/* We define these mov expanders to match the standard mov$a optab to prevent
|
||||
the mid-end from trying to do a subreg for these modes which is the most
|
||||
@ -1066,7 +1067,7 @@
|
||||
(define_insn "vashl<mode>3"
|
||||
[(set (match_operand:VDQIW 0 "s_register_operand" "=w,w")
|
||||
(ashift:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w,w")
|
||||
(match_operand:VDQIW 2 "imm_lshift_or_reg_neon" "w,Dn")))]
|
||||
(match_operand:VDQIW 2 "imm_lshift_or_reg_neon" "w,Dm")))]
|
||||
"TARGET_NEON"
|
||||
{
|
||||
switch (which_alternative)
|
||||
@ -1085,7 +1086,7 @@
|
||||
(define_insn "vashr<mode>3_imm"
|
||||
[(set (match_operand:VDQIW 0 "s_register_operand" "=w")
|
||||
(ashiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")
|
||||
(match_operand:VDQIW 2 "imm_for_neon_rshift_operand" "Dn")))]
|
||||
(match_operand:VDQIW 2 "imm_for_neon_rshift_operand" "Dm")))]
|
||||
"TARGET_NEON"
|
||||
{
|
||||
return neon_output_shift_immediate ("vshr", 's', &operands[2],
|
||||
@ -1098,7 +1099,7 @@
|
||||
(define_insn "vlshr<mode>3_imm"
|
||||
[(set (match_operand:VDQIW 0 "s_register_operand" "=w")
|
||||
(lshiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")
|
||||
(match_operand:VDQIW 2 "imm_for_neon_rshift_operand" "Dn")))]
|
||||
(match_operand:VDQIW 2 "imm_for_neon_rshift_operand" "Dm")))]
|
||||
"TARGET_NEON"
|
||||
{
|
||||
return neon_output_shift_immediate ("vshr", 'u', &operands[2],
|
||||
|
@ -1,3 +1,8 @@
|
||||
2019-04-09 Matthew Malcomson <matthew.malcomson@arm.com>
|
||||
|
||||
PR target/90024
|
||||
* gcc.dg/torture/neon-immediate-timode.c: New test.
|
||||
|
||||
2019-04-09 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR tree-optimization/89998
|
||||
|
10
gcc/testsuite/gcc.dg/torture/neon-immediate-timode.c
Normal file
10
gcc/testsuite/gcc.dg/torture/neon-immediate-timode.c
Normal file
@ -0,0 +1,10 @@
|
||||
union a {
|
||||
char b;
|
||||
long long c;
|
||||
};
|
||||
union a d;
|
||||
int g(int, union a, union a);
|
||||
void e() {
|
||||
union a f[2] = {-1L};
|
||||
g(0, d, f[0]);
|
||||
}
|
Loading…
Reference in New Issue
Block a user