From 66b01cc3421055806f51ac36a8d237536970504c Mon Sep 17 00:00:00 2001 From: Andrew Stubbs Date: Tue, 7 Jan 2020 14:35:21 +0000 Subject: [PATCH] Disallow 'B' constraints on amdgcn addc/subb 2020-01-07 Andrew Stubbs gcc/ * config/gcn/constraints.md (DA): Update description and match. (DB): Likewise. (Db): New constraint. * config/gcn/gcn-protos.h (gcn_inline_constant64_p): Add second parameter. * config/gcn/gcn.c (gcn_inline_constant64_p): Add 'mixed' parameter. Implement 'Db' mixed immediate type. * config/gcn/gcn-valu.md (addcv64si3): Rework constraints. (addcv64si3_dup): Delete. (subcv64si3): Rework constraints. (addv64di3): Rework constraints. (addv64di3_exec): Rework constraints. (subv64di3): Rework constraints. (addv64di3_dup): Delete. (addv64di3_dup_exec): Delete. (addv64di3_zext): Rework constraints. (addv64di3_zext_exec): Rework constraints. (addv64di3_zext_dup): Rework constraints. (addv64di3_zext_dup_exec): Rework constraints. (addv64di3_zext_dup2): Rework constraints. (addv64di3_zext_dup2_exec): Rework constraints. (addv64di3_sext_dup2): Rework constraints. (addv64di3_sext_dup2_exec): Rework constraints. From-SVN: r279959 --- gcc/ChangeLog | 26 +++++ gcc/config/gcn/constraints.md | 11 +- gcc/config/gcn/gcn-protos.h | 2 +- gcc/config/gcn/gcn-valu.md | 206 +++++++++------------------------- gcc/config/gcn/gcn.c | 10 +- 5 files changed, 96 insertions(+), 159 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3609886fee6..56d45ab3616 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,29 @@ +2020-01-07 Andrew Stubbs + + * config/gcn/constraints.md (DA): Update description and match. + (DB): Likewise. + (Db): New constraint. + * config/gcn/gcn-protos.h (gcn_inline_constant64_p): Add second + parameter. + * config/gcn/gcn.c (gcn_inline_constant64_p): Add 'mixed' parameter. + Implement 'Db' mixed immediate type. + * config/gcn/gcn-valu.md (addcv64si3): Rework constraints. + (addcv64si3_dup): Delete. + (subcv64si3): Rework constraints. + (addv64di3): Rework constraints. + (addv64di3_exec): Rework constraints. + (subv64di3): Rework constraints. + (addv64di3_dup): Delete. + (addv64di3_dup_exec): Delete. + (addv64di3_zext): Rework constraints. + (addv64di3_zext_exec): Rework constraints. + (addv64di3_zext_dup): Rework constraints. + (addv64di3_zext_dup_exec): Rework constraints. + (addv64di3_zext_dup2): Rework constraints. + (addv64di3_zext_dup2_exec): Rework constraints. + (addv64di3_sext_dup2): Rework constraints. + (addv64di3_sext_dup2_exec): Rework constraints. + 2020-01-07 Andre Vieira * doc/sourcebuild.texi (arm_little_endian, arm_nothumb): Documented diff --git a/gcc/config/gcn/constraints.md b/gcc/config/gcn/constraints.md index f2de943ba16..dd6615b0fd7 100644 --- a/gcc/config/gcn/constraints.md +++ b/gcc/config/gcn/constraints.md @@ -53,12 +53,17 @@ (match_test "gcn_constant64_p (op)"))) (define_constraint "DA" - "Splittable inline immediate 64-bit parameter" + "Immediate 64-bit parameter, low and high part match 'A'" (and (match_code "const_int,const_double,const_vector") - (match_test "gcn_inline_constant64_p (op)"))) + (match_test "gcn_inline_constant64_p (op, 0)"))) + +(define_constraint "Db" + "Immediate 64-bit parameter, low part matches 'B', high part matches 'A'" + (and (match_code "const_int,const_double,const_vector") + (match_test "gcn_inline_constant64_p (op, 1)"))) (define_constraint "DB" - "Splittable immediate 64-bit parameter" + "Immediate 64-bit parameter, low and high part match 'B'" (match_code "const_int,const_double,const_vector")) (define_constraint "U" diff --git a/gcc/config/gcn/gcn-protos.h b/gcc/config/gcn/gcn-protos.h index 92a6aa77e84..e4dadd37f21 100644 --- a/gcc/config/gcn/gcn-protos.h +++ b/gcc/config/gcn/gcn-protos.h @@ -51,7 +51,7 @@ extern int gcn_hard_regno_nregs (int regno, machine_mode mode); extern void gcn_hsa_declare_function_name (FILE *file, const char *name, tree decl); extern HOST_WIDE_INT gcn_initial_elimination_offset (int, int); -extern bool gcn_inline_constant64_p (rtx); +extern bool gcn_inline_constant64_p (rtx, bool); extern bool gcn_inline_constant_p (rtx); extern int gcn_inline_fp_constant_p (rtx, bool); extern reg_class gcn_mode_code_base_reg_class (machine_mode, addr_space_t, diff --git a/gcc/config/gcn/gcn-valu.md b/gcc/config/gcn/gcn-valu.md index e301a4356ec..7dd7bb96918 100644 --- a/gcc/config/gcn/gcn-valu.md +++ b/gcc/config/gcn/gcn-valu.md @@ -1090,20 +1090,21 @@ [(set_attr "type" "vop2,vop3b") (set_attr "length" "8,8")]) -; This pattern does not accept SGPR because VCC read already counts as an -; SGPR use and number of SGPR operands is limited to 1. +; v_addc does not accept an SGPR because the VCC read already counts as an +; SGPR use and the number of SGPR operands is limited to 1. It does not +; accept "B" immediate constants due to a related bus conflict. (define_insn "addcv64si3" - [(set (match_operand:V64SI 0 "register_operand" "=v,v") + [(set (match_operand:V64SI 0 "register_operand" "=v, v") (plus:V64SI (plus:V64SI (vec_merge:V64SI (vec_duplicate:V64SI (const_int 1)) (vec_duplicate:V64SI (const_int 0)) - (match_operand:DI 3 "register_operand" " cV,Sv")) - (match_operand:V64SI 1 "gcn_alu_operand" "%vA,vA")) - (match_operand:V64SI 2 "gcn_alu_operand" " vB,vB"))) - (set (match_operand:DI 4 "register_operand" "=cV,Sg") + (match_operand:DI 3 "register_operand" " cV,cVSv")) + (match_operand:V64SI 1 "gcn_alu_operand" "% v, vA")) + (match_operand:V64SI 2 "gcn_alu_operand" " vA, vA"))) + (set (match_operand:DI 4 "register_operand" "=cV,cVSg") (ior:DI (ltu:DI (plus:V64SI (plus:V64SI (vec_merge:V64SI @@ -1121,40 +1122,7 @@ (match_dup 1)) (match_dup 1))))] "" - "v_addc%^_u32\t%0, %4, %1, %2, %3" - [(set_attr "type" "vop2,vop3b") - (set_attr "length" "4,8")]) - -(define_insn "addcv64si3_dup" - [(set (match_operand:V64SI 0 "register_operand" "=v,v") - (plus:V64SI - (plus:V64SI - (vec_merge:V64SI - (vec_duplicate:V64SI (const_int 1)) - (vec_duplicate:V64SI (const_int 0)) - (match_operand:DI 3 "register_operand" " cV, Sv")) - (match_operand:V64SI 1 "gcn_alu_operand" "%vA, vA")) - (vec_duplicate:V64SI - (match_operand:SI 2 "gcn_alu_operand" "SvB,SvB")))) - (set (match_operand:DI 4 "register_operand" "=cV, Sg") - (ior:DI (ltu:DI (plus:V64SI (plus:V64SI - (vec_merge:V64SI - (vec_duplicate:V64SI (const_int 1)) - (vec_duplicate:V64SI (const_int 0)) - (match_dup 3)) - (match_dup 1)) - (vec_duplicate:V64SI - (match_dup 2))) - (vec_duplicate:V64SI - (match_dup 2))) - (ltu:DI (plus:V64SI (vec_merge:V64SI - (vec_duplicate:V64SI (const_int 1)) - (vec_duplicate:V64SI (const_int 0)) - (match_dup 3)) - (match_dup 1)) - (match_dup 1))))] - "" - "v_addc%^_u32\t%0, %4, %1, %2, %3" + "v_addc%^_u32\t%0, %4, %2, %1, %3" [(set_attr "type" "vop2,vop3b") (set_attr "length" "4,8")]) @@ -1188,8 +1156,9 @@ [(set_attr "type" "vop2,vop3b,vop2,vop3b") (set_attr "length" "8")]) -; This pattern does not accept SGPR because VCC read already counts -; as a SGPR use and number of SGPR operands is limited to 1. +; v_subb does not accept an SGPR because the VCC read already counts as an +; SGPR use and the number of SGPR operands is limited to 1. It does not +; accept "B" immediate constants due to a related bus conflict. (define_insn "subcv64si3" [(set (match_operand:V64SI 0 "register_operand" "= v, v, v, v") @@ -1198,10 +1167,10 @@ (vec_merge:V64SI (vec_duplicate:V64SI (const_int 1)) (vec_duplicate:V64SI (const_int 0)) - (match_operand:DI 3 "gcn_alu_operand" " cV,Sv,cV,Sv")) - (match_operand:V64SI 1 "gcn_alu_operand" " vA,vA,vB,vB")) - (match_operand:V64SI 2 "gcn_alu_operand" " vB,vB,vA,vA"))) - (set (match_operand:DI 4 "register_operand" "=cV,Sg,cV,Sg") + (match_operand:DI 3 "gcn_alu_operand" " cV,cVSv,cV,cVSv")) + (match_operand:V64SI 1 "gcn_alu_operand" " vA, vA, v, vA")) + (match_operand:V64SI 2 "gcn_alu_operand" " v, vA,vA, vA"))) + (set (match_operand:DI 4 "register_operand" "=cV,cVSg,cV,cVSg") (ior:DI (gtu:DI (minus:V64SI (minus:V64SI (vec_merge:V64SI (vec_duplicate:V64SI (const_int 1)) @@ -1223,13 +1192,13 @@ v_subbrev%^_u32\t%0, %4, %2, %1, %3 v_subbrev%^_u32\t%0, %4, %2, %1, %3" [(set_attr "type" "vop2,vop3b,vop2,vop3b") - (set_attr "length" "8")]) + (set_attr "length" "4,8,4,8")]) (define_insn_and_split "addv64di3" - [(set (match_operand:V64DI 0 "register_operand" "= &v") + [(set (match_operand:V64DI 0 "register_operand" "= &v, &v") (plus:V64DI - (match_operand:V64DI 1 "register_operand" "% v0") - (match_operand:V64DI 2 "gcn_alu_operand" "vSvB0"))) + (match_operand:V64DI 1 "register_operand" "%vDb,vDb0") + (match_operand:V64DI 2 "gcn_alu_operand" "vDb0, vDb"))) (clobber (reg:DI VCC_REG))] "" "#" @@ -1255,13 +1224,13 @@ (set_attr "length" "8")]) (define_insn_and_split "addv64di3_exec" - [(set (match_operand:V64DI 0 "register_operand" "= &v") + [(set (match_operand:V64DI 0 "register_operand" "= &v, &v") (vec_merge:V64DI (plus:V64DI - (match_operand:V64DI 1 "register_operand" "% v0") - (match_operand:V64DI 2 "gcn_alu_operand" "vSvB0")) - (match_operand:V64DI 3 "gcn_register_or_unspec_operand" " U0") - (match_operand:DI 4 "gcn_exec_reg_operand" " e"))) + (match_operand:V64DI 1 "register_operand" "%vDb,vDb0") + (match_operand:V64DI 2 "gcn_alu_operand" "vDb0, vDb")) + (match_operand:V64DI 3 "gcn_register_or_unspec_operand" " U0, U0") + (match_operand:DI 4 "gcn_exec_reg_operand" " e, e"))) (clobber (reg:DI VCC_REG))] "" "#" @@ -1292,10 +1261,10 @@ (set_attr "length" "8")]) (define_insn_and_split "subv64di3" - [(set (match_operand:V64DI 0 "register_operand" "= &v, &v, &v, &v") + [(set (match_operand:V64DI 0 "register_operand" "=&v, &v, &v, &v") (minus:V64DI - (match_operand:V64DI 1 "gcn_alu_operand" "vSvB,vSvB0, v, v0") - (match_operand:V64DI 2 "gcn_alu_operand" " v0, v,vSvB0,vSvB"))) + (match_operand:V64DI 1 "gcn_alu_operand" "vDb,vDb0, v, v0") + (match_operand:V64DI 2 "gcn_alu_operand" " v0, v,vDb0,vDb"))) (clobber (reg:DI VCC_REG))] "" "#" @@ -1359,80 +1328,12 @@ [(set_attr "type" "vmult") (set_attr "length" "8")]) -(define_insn_and_split "addv64di3_dup" - [(set (match_operand:V64DI 0 "register_operand" "= &v") - (plus:V64DI - (match_operand:V64DI 1 "register_operand" " v0") - (vec_duplicate:V64DI - (match_operand:DI 2 "gcn_alu_operand" "SvDB")))) - (clobber (reg:DI VCC_REG))] - "" - "#" - "gcn_can_split_p (V64DImode, operands[0]) - && gcn_can_split_p (V64DImode, operands[1]) - && gcn_can_split_p (V64DImode, operands[2])" - [(const_int 0)] - { - rtx vcc = gen_rtx_REG (DImode, VCC_REG); - emit_insn (gen_addv64si3_vcc_dup - (gcn_operand_part (V64DImode, operands[0], 0), - gcn_operand_part (DImode, operands[2], 0), - gcn_operand_part (V64DImode, operands[1], 0), - vcc)); - emit_insn (gen_addcv64si3_dup - (gcn_operand_part (V64DImode, operands[0], 1), - gcn_operand_part (V64DImode, operands[1], 1), - gcn_operand_part (DImode, operands[2], 1), - vcc, vcc)); - DONE; - } - [(set_attr "type" "vmult") - (set_attr "length" "8")]) - -(define_insn_and_split "addv64di3_dup_exec" - [(set (match_operand:V64DI 0 "register_operand" "= &v") - (vec_merge:V64DI - (plus:V64DI - (match_operand:V64DI 1 "register_operand" " v0") - (vec_duplicate:V64DI - (match_operand:DI 2 "gcn_alu_operand" "SvDB"))) - (match_operand:V64DI 3 "gcn_register_or_unspec_operand" " U0") - (match_operand:DI 4 "gcn_exec_reg_operand" " e"))) - (clobber (reg:DI VCC_REG))] - "" - "#" - "gcn_can_split_p (V64DImode, operands[0]) - && gcn_can_split_p (V64DImode, operands[1]) - && gcn_can_split_p (V64DImode, operands[2]) - && gcn_can_split_p (V64DImode, operands[3])" - [(const_int 0)] - { - rtx vcc = gen_rtx_REG (DImode, VCC_REG); - emit_insn (gen_addv64si3_vcc_dup_exec - (gcn_operand_part (V64DImode, operands[0], 0), - gcn_operand_part (DImode, operands[2], 0), - gcn_operand_part (V64DImode, operands[1], 0), - vcc, - gcn_operand_part (V64DImode, operands[3], 0), - operands[4])); - emit_insn (gen_addcv64si3_dup_exec - (gcn_operand_part (V64DImode, operands[0], 1), - gcn_operand_part (V64DImode, operands[1], 1), - gcn_operand_part (DImode, operands[2], 1), - vcc, vcc, - gcn_operand_part (V64DImode, operands[3], 1), - operands[4])); - DONE; - } - [(set_attr "type" "vmult") - (set_attr "length" "8")]) - (define_insn_and_split "addv64di3_zext" - [(set (match_operand:V64DI 0 "register_operand" "=&v,&v") + [(set (match_operand:V64DI 0 "register_operand" "=&v, &v, &v, &v") (plus:V64DI (zero_extend:V64DI - (match_operand:V64SI 1 "gcn_alu_operand" "0vA,0vB")) - (match_operand:V64DI 2 "gcn_alu_operand" "0vB,0vA"))) + (match_operand:V64SI 1 "gcn_alu_operand" "0vA,0vB, vA, vB")) + (match_operand:V64DI 2 "gcn_alu_operand" "vDb,vDA,0vDb,0vDA"))) (clobber (reg:DI VCC_REG))] "" "#" @@ -1453,17 +1354,18 @@ DONE; } [(set_attr "type" "vmult") - (set_attr "length" "8,8")]) + (set_attr "length" "8")]) (define_insn_and_split "addv64di3_zext_exec" - [(set (match_operand:V64DI 0 "register_operand" "=&v,&v") + [(set (match_operand:V64DI 0 "register_operand" "=&v, &v, &v, &v") (vec_merge:V64DI (plus:V64DI (zero_extend:V64DI - (match_operand:V64SI 1 "gcn_alu_operand" "0vA,0vB")) - (match_operand:V64DI 2 "gcn_alu_operand" "0vB,0vA")) - (match_operand:V64DI 3 "gcn_register_or_unspec_operand" " U0, U0") - (match_operand:DI 4 "gcn_exec_reg_operand" " e, e"))) + (match_operand:V64SI 1 "gcn_alu_operand" "0vA, vA,0vB, vB")) + (match_operand:V64DI 2 "gcn_alu_operand" "vDb,0vDb,vDA,0vDA")) + (match_operand:V64DI 3 "gcn_register_or_unspec_operand" + " U0, U0, U0, U0") + (match_operand:DI 4 "gcn_exec_reg_operand" " e, e, e, e"))) (clobber (reg:DI VCC_REG))] "" "#" @@ -1489,15 +1391,15 @@ DONE; } [(set_attr "type" "vmult") - (set_attr "length" "8,8")]) + (set_attr "length" "8")]) (define_insn_and_split "addv64di3_zext_dup" - [(set (match_operand:V64DI 0 "register_operand" "=&v") + [(set (match_operand:V64DI 0 "register_operand" "= &v, &v") (plus:V64DI (zero_extend:V64DI (vec_duplicate:V64SI - (match_operand:SI 1 "gcn_alu_operand" "BSv"))) - (match_operand:V64DI 2 "gcn_alu_operand" "vA0"))) + (match_operand:SI 1 "gcn_alu_operand" " BSv, ASv"))) + (match_operand:V64DI 2 "gcn_alu_operand" "vDA0,vDb0"))) (clobber (reg:DI VCC_REG))] "" "#" @@ -1521,15 +1423,15 @@ (set_attr "length" "8")]) (define_insn_and_split "addv64di3_zext_dup_exec" - [(set (match_operand:V64DI 0 "register_operand" "=&v") + [(set (match_operand:V64DI 0 "register_operand" "= &v, &v") (vec_merge:V64DI (plus:V64DI (zero_extend:V64DI (vec_duplicate:V64SI - (match_operand:SI 1 "gcn_alu_operand" "BSv"))) - (match_operand:V64DI 2 "gcn_alu_operand" "vA0")) - (match_operand:V64DI 3 "gcn_register_or_unspec_operand" " U0") - (match_operand:DI 4 "gcn_exec_reg_operand" " e"))) + (match_operand:SI 1 "gcn_alu_operand" " ASv, BSv"))) + (match_operand:V64DI 2 "gcn_alu_operand" "vDb0,vDA0")) + (match_operand:V64DI 3 "gcn_register_or_unspec_operand" " U0, U0") + (match_operand:DI 4 "gcn_exec_reg_operand" " e, e"))) (clobber (reg:DI VCC_REG))] "" "#" @@ -1558,10 +1460,10 @@ (set_attr "length" "8")]) (define_insn_and_split "addv64di3_zext_dup2" - [(set (match_operand:V64DI 0 "register_operand" "= v") + [(set (match_operand:V64DI 0 "register_operand" "= &v") (plus:V64DI (zero_extend:V64DI (match_operand:V64SI 1 "gcn_alu_operand" " vA")) - (vec_duplicate:V64DI (match_operand:DI 2 "gcn_alu_operand" "BSv")))) + (vec_duplicate:V64DI (match_operand:DI 2 "gcn_alu_operand" "DbSv")))) (clobber (reg:DI VCC_REG))] "" "#" @@ -1584,7 +1486,7 @@ (set_attr "length" "8")]) (define_insn_and_split "addv64di3_zext_dup2_exec" - [(set (match_operand:V64DI 0 "register_operand" "= v") + [(set (match_operand:V64DI 0 "register_operand" "=&v") (vec_merge:V64DI (plus:V64DI (zero_extend:V64DI (match_operand:V64SI 1 "gcn_alu_operand" @@ -1621,7 +1523,7 @@ (set_attr "length" "8")]) (define_insn_and_split "addv64di3_sext_dup2" - [(set (match_operand:V64DI 0 "register_operand" "= v") + [(set (match_operand:V64DI 0 "register_operand" "=&v") (plus:V64DI (sign_extend:V64DI (match_operand:V64SI 1 "gcn_alu_operand" " vA")) (vec_duplicate:V64DI (match_operand:DI 2 "gcn_alu_operand" "BSv")))) @@ -1649,7 +1551,7 @@ (set_attr "length" "8")]) (define_insn_and_split "addv64di3_sext_dup2_exec" - [(set (match_operand:V64DI 0 "register_operand" "= v") + [(set (match_operand:V64DI 0 "register_operand" "=&v") (vec_merge:V64DI (plus:V64DI (sign_extend:V64DI (match_operand:V64SI 1 "gcn_alu_operand" @@ -3201,9 +3103,11 @@ { rtx tmp = gen_reg_rtx (V64DImode); rtx v1 = gen_rtx_REG (V64SImode, VGPR_REGNO (1)); + rtx op1vec = gen_reg_rtx (V64DImode); emit_insn (gen_mulv64di3_zext_dup2 (tmp, v1, operands[2])); - emit_insn (gen_addv64di3_dup (operands[0], tmp, operands[1])); + emit_insn (gen_vec_duplicatev64si (op1vec, operands[1])); + emit_insn (gen_addv64di3 (operands[0], tmp, op1vec)); DONE; }) diff --git a/gcc/config/gcn/gcn.c b/gcc/config/gcn/gcn.c index b361cffbb84..4056f7257b5 100644 --- a/gcc/config/gcn/gcn.c +++ b/gcc/config/gcn/gcn.c @@ -902,16 +902,17 @@ gcn_constant_p (rtx x) /* Return true if X is a constant representable as two inline immediate constants in a 64-bit instruction that is split into two 32-bit - instructions. */ + instructions. + When MIXED is set, the low-part is permitted to use the full 32-bits. */ bool -gcn_inline_constant64_p (rtx x) +gcn_inline_constant64_p (rtx x, bool mixed) { if (GET_CODE (x) == CONST_VECTOR) { if (!vgpr_vector_mode_p (GET_MODE (x))) return false; - if (!gcn_inline_constant64_p (CONST_VECTOR_ELT (x, 0))) + if (!gcn_inline_constant64_p (CONST_VECTOR_ELT (x, 0), mixed)) return false; for (int i = 1; i < 64; i++) if (CONST_VECTOR_ELT (x, i) != CONST_VECTOR_ELT (x, 0)) @@ -925,7 +926,8 @@ gcn_inline_constant64_p (rtx x) rtx val_lo = gcn_operand_part (DImode, x, 0); rtx val_hi = gcn_operand_part (DImode, x, 1); - return gcn_inline_constant_p (val_lo) && gcn_inline_constant_p (val_hi); + return ((mixed || gcn_inline_constant_p (val_lo)) + && gcn_inline_constant_p (val_hi)); } /* Return true if X is a constant representable as an immediate constant -- 2.30.2