diff options
author | Andrew Stubbs <ams@codesourcery.com> | 2020-05-13 16:05:54 +0100 |
---|---|---|
committer | Andrew Stubbs <ams@codesourcery.com> | 2020-05-14 20:45:09 +0100 |
commit | 75d0b3d728864116144f9db52b156c573ae8d879 (patch) | |
tree | fb76ce9b448d07876e380edabe7ca129a0d96141 /gcc/config/gcn | |
parent | 9056cd80351c65c3b9a3257644236f2007c46a3f (diff) |
amdgcn: fix vcc clobber in vector load/store
This switches the code that expands scalar addresses to vectors of addresses
from using VCC to using CC_SAVE_REG, for the lo-part to hi-part carry values.
These were fine in code expanded in earlier passes, but addresses expanded
late, such as for stack spills or reloads, could clobber live VCC values,
causing execution failures.
This is the first target-specific testcase for GCN, so the new .exp file is
included.
2020-05-14 Andrew Stubbs <ams@codesourcery.com>
gcc/
* config/gcn/gcn-valu.md (add<mode>3_zext_dup): Change to a
define_expand, and rename the original to ...
(add<mode>3_vcc_zext_dup): ... this, and add a custom VCC operand.
(add<mode>3_zext_dup_exec): Likewise, with ...
(add<mode>3_vcc_zext_dup_exec): ... this.
(add<mode>3_zext_dup2): Likewise, with ...
(add<mode>3_zext_dup_exec): ... this.
(add<mode>3_zext_dup2_exec): Likewise, with ...
(add<mode>3_zext_dup2): ... this.
* config/gcn/gcn.c (gcn_expand_scalar_to_vector_address): Switch
addv64di3_zext* calls to use addv64di3_vcc_zext*.
gcc/testsuite/
* testsuite/gcc.target/gcn/gcn.exp: New file.
* testsuite/gcc.target/gcn/vcc-clobber.c: New file.
Diffstat (limited to 'gcc/config/gcn')
-rw-r--r-- | gcc/config/gcn/gcn-valu.md | 161 | ||||
-rw-r--r-- | gcc/config/gcn/gcn.c | 13 |
2 files changed, 123 insertions, 51 deletions
diff --git a/gcc/config/gcn/gcn-valu.md b/gcc/config/gcn/gcn-valu.md index d3badb4059c..a43d6b6c6f3 100644 --- a/gcc/config/gcn/gcn-valu.md +++ b/gcc/config/gcn/gcn-valu.md @@ -1379,135 +1379,206 @@ [(set_attr "type" "vmult") (set_attr "length" "8")]) -(define_insn_and_split "add<mode>3_zext_dup" - [(set (match_operand:V_DI 0 "register_operand" "= v, v") +(define_insn_and_split "add<mode>3_vcc_zext_dup" + [(set (match_operand:V_DI 0 "register_operand" "= v, v") (plus:V_DI (zero_extend:V_DI (vec_duplicate:<VnSI> - (match_operand:SI 1 "gcn_alu_operand" "BSv,ASv"))) - (match_operand:V_DI 2 "gcn_alu_operand" "vDA,vDb"))) - (clobber (reg:DI VCC_REG))] + (match_operand:SI 1 "gcn_alu_operand" " BSv, ASv"))) + (match_operand:V_DI 2 "gcn_alu_operand" " vDA, vDb"))) + (set (match_operand:DI 3 "register_operand" "=SgcV,SgcV") + (ltu:DI (plus:V_DI + (zero_extend:V_DI (vec_duplicate:<VnSI> (match_dup 1))) + (match_dup 2)) + (match_dup 1)))] "" "#" "gcn_can_split_p (<MODE>mode, operands[0]) && gcn_can_split_p (<MODE>mode, operands[2])" [(const_int 0)] { - rtx vcc = gen_rtx_REG (DImode, VCC_REG); emit_insn (gen_add<vnsi>3_vcc_dup (gcn_operand_part (<MODE>mode, operands[0], 0), gcn_operand_part (DImode, operands[1], 0), gcn_operand_part (<MODE>mode, operands[2], 0), - vcc)); + operands[3])); emit_insn (gen_addc<vnsi>3 (gcn_operand_part (<MODE>mode, operands[0], 1), gcn_operand_part (<MODE>mode, operands[2], 1), - const0_rtx, vcc, vcc)); + const0_rtx, operands[3], operands[3])); DONE; } [(set_attr "type" "vmult") (set_attr "length" "8")]) -(define_insn_and_split "add<mode>3_zext_dup_exec" - [(set (match_operand:V_DI 0 "register_operand" "= v, v") +(define_expand "add<mode>3_zext_dup" + [(match_operand:V_DI 0 "register_operand") + (match_operand:SI 1 "gcn_alu_operand") + (match_operand:V_DI 2 "gcn_alu_operand")] + "" + { + rtx vcc = gen_rtx_REG (DImode, VCC_REG); + emit_insn (gen_add<mode>3_vcc_zext_dup (operands[0], operands[1], + operands[2], vcc)); + DONE; + }) + +(define_insn_and_split "add<mode>3_vcc_zext_dup_exec" + [(set (match_operand:V_DI 0 "register_operand" "= v, v") (vec_merge:V_DI (plus:V_DI (zero_extend:V_DI (vec_duplicate:<VnSI> - (match_operand:SI 1 "gcn_alu_operand" "ASv,BSv"))) - (match_operand:V_DI 2 "gcn_alu_operand" "vDb,vDA")) - (match_operand:V_DI 3 "gcn_register_or_unspec_operand" " U0, U0") - (match_operand:DI 4 "gcn_exec_reg_operand" " e, e"))) - (clobber (reg:DI VCC_REG))] + (match_operand:SI 1 "gcn_alu_operand" " ASv, BSv"))) + (match_operand:V_DI 2 "gcn_alu_operand" " vDb, vDA")) + (match_operand:V_DI 4 "gcn_register_or_unspec_operand" " U0, U0") + (match_operand:DI 5 "gcn_exec_reg_operand" " e, e"))) + (set (match_operand:DI 3 "register_operand" "=SgcV,SgcV") + (and:DI + (ltu:DI (plus:V_DI + (zero_extend:V_DI (vec_duplicate:<VnSI> (match_dup 1))) + (match_dup 2)) + (match_dup 1)) + (match_dup 5)))] "" "#" "gcn_can_split_p (<MODE>mode, operands[0]) && gcn_can_split_p (<MODE>mode, operands[2]) - && gcn_can_split_p (<MODE>mode, operands[3])" + && gcn_can_split_p (<MODE>mode, operands[4])" [(const_int 0)] { - rtx vcc = gen_rtx_REG (DImode, VCC_REG); emit_insn (gen_add<vnsi>3_vcc_dup_exec (gcn_operand_part (<MODE>mode, operands[0], 0), gcn_operand_part (DImode, operands[1], 0), gcn_operand_part (<MODE>mode, operands[2], 0), - vcc, - gcn_operand_part (<MODE>mode, operands[3], 0), - operands[4])); + operands[3], + gcn_operand_part (<MODE>mode, operands[4], 0), + operands[5])); emit_insn (gen_addc<vnsi>3_exec (gcn_operand_part (<MODE>mode, operands[0], 1), gcn_operand_part (<MODE>mode, operands[2], 1), - const0_rtx, vcc, vcc, - gcn_operand_part (<MODE>mode, operands[3], 1), - operands[4])); + const0_rtx, operands[3], operands[3], + gcn_operand_part (<MODE>mode, operands[4], 1), + operands[5])); DONE; } [(set_attr "type" "vmult") (set_attr "length" "8")]) -(define_insn_and_split "add<mode>3_zext_dup2" - [(set (match_operand:V_DI 0 "register_operand" "= v") +(define_expand "add<mode>3_zext_dup_exec" + [(match_operand:V_DI 0 "register_operand") + (match_operand:SI 1 "gcn_alu_operand") + (match_operand:V_DI 2 "gcn_alu_operand") + (match_operand:V_DI 3 "gcn_register_or_unspec_operand") + (match_operand:DI 4 "gcn_exec_reg_operand")] + "" + { + rtx vcc = gen_rtx_REG (DImode, VCC_REG); + emit_insn (gen_add<mode>3_vcc_zext_dup_exec (operands[0], operands[1], + operands[2], vcc, operands[3], + operands[4])); + DONE; + }) + +(define_insn_and_split "add<mode>3_vcc_zext_dup2" + [(set (match_operand:V_DI 0 "register_operand" "= v") (plus:V_DI (zero_extend:V_DI (match_operand:<VnSI> 1 "gcn_alu_operand" " vA")) - (vec_duplicate:V_DI (match_operand:DI 2 "gcn_alu_operand" "DbSv")))) - (clobber (reg:DI VCC_REG))] + (vec_duplicate:V_DI (match_operand:DI 2 "gcn_alu_operand" " DbSv")))) + (set (match_operand:DI 3 "register_operand" "=SgcV") + (ltu:DI (plus:V_DI + (zero_extend:V_DI (match_dup 1)) + (vec_duplicate:V_DI (match_dup 2))) + (match_dup 1)))] "" "#" "gcn_can_split_p (<MODE>mode, operands[0])" [(const_int 0)] { - rtx vcc = gen_rtx_REG (DImode, VCC_REG); emit_insn (gen_add<vnsi>3_vcc_dup (gcn_operand_part (<MODE>mode, operands[0], 0), gcn_operand_part (DImode, operands[2], 0), operands[1], - vcc)); + operands[3])); rtx dsthi = gcn_operand_part (<MODE>mode, operands[0], 1); emit_insn (gen_vec_duplicate<vnsi> (dsthi, gcn_operand_part (DImode, operands[2], 1))); - emit_insn (gen_addc<vnsi>3 (dsthi, dsthi, const0_rtx, vcc, vcc)); + emit_insn (gen_addc<vnsi>3 (dsthi, dsthi, const0_rtx, operands[3], + operands[3])); DONE; } [(set_attr "type" "vmult") (set_attr "length" "8")]) -(define_insn_and_split "add<mode>3_zext_dup2_exec" - [(set (match_operand:V_DI 0 "register_operand" "= v") +(define_expand "add<mode>3_zext_dup2" + [(match_operand:V_DI 0 "register_operand") + (match_operand:<VnSI> 1 "gcn_alu_operand") + (match_operand:DI 2 "gcn_alu_operand")] + "" + { + rtx vcc = gen_rtx_REG (DImode, VCC_REG); + emit_insn (gen_add<mode>3_vcc_zext_dup2 (operands[0], operands[1], + operands[2], vcc)); + DONE; + }) + +(define_insn_and_split "add<mode>3_vcc_zext_dup2_exec" + [(set (match_operand:V_DI 0 "register_operand" "= v") (vec_merge:V_DI (plus:V_DI (zero_extend:V_DI (match_operand:<VnSI> 1 "gcn_alu_operand" "vA")) (vec_duplicate:V_DI (match_operand:DI 2 "gcn_alu_operand" "BSv"))) - (match_operand:V_DI 3 "gcn_register_or_unspec_operand" " U0") - (match_operand:DI 4 "gcn_exec_reg_operand" " e"))) - (clobber (reg:DI VCC_REG))] + (match_operand:V_DI 4 "gcn_register_or_unspec_operand" " U0") + (match_operand:DI 5 "gcn_exec_reg_operand" " e"))) + (set (match_operand:DI 3 "register_operand" "=SgcV") + (and:DI + (ltu:DI (plus:V_DI + (zero_extend:V_DI (match_dup 1)) + (vec_duplicate:V_DI (match_dup 2))) + (match_dup 1)) + (match_dup 5)))] "" "#" "gcn_can_split_p (<MODE>mode, operands[0]) - && gcn_can_split_p (<MODE>mode, operands[3])" + && gcn_can_split_p (<MODE>mode, operands[4])" [(const_int 0)] { - rtx vcc = gen_rtx_REG (DImode, VCC_REG); emit_insn (gen_add<vnsi>3_vcc_dup_exec (gcn_operand_part (<MODE>mode, operands[0], 0), gcn_operand_part (DImode, operands[2], 0), operands[1], - vcc, - gcn_operand_part (<MODE>mode, operands[3], 0), - operands[4])); + operands[3], + gcn_operand_part (<MODE>mode, operands[4], 0), + operands[5])); rtx dsthi = gcn_operand_part (<MODE>mode, operands[0], 1); emit_insn (gen_vec_duplicate<vnsi>_exec (dsthi, gcn_operand_part (DImode, operands[2], 1), - gcn_operand_part (<MODE>mode, operands[3], 1), - operands[4])); + gcn_operand_part (<MODE>mode, operands[4], 1), + operands[5])); emit_insn (gen_addc<vnsi>3_exec - (dsthi, dsthi, const0_rtx, vcc, vcc, - gcn_operand_part (<MODE>mode, operands[3], 1), - operands[4])); + (dsthi, dsthi, const0_rtx, operands[3], operands[3], + gcn_operand_part (<MODE>mode, operands[4], 1), + operands[5])); DONE; } [(set_attr "type" "vmult") (set_attr "length" "8")]) +(define_expand "add<mode>3_zext_dup2_exec" + [(match_operand:V_DI 0 "register_operand") + (match_operand:<VnSI> 1 "gcn_alu_operand") + (match_operand:DI 2 "gcn_alu_operand") + (match_operand:V_DI 3 "gcn_register_or_unspec_operand") + (match_operand:DI 4 "gcn_exec_reg_operand")] + "" + { + rtx vcc = gen_rtx_REG (DImode, VCC_REG); + emit_insn (gen_add<mode>3_vcc_zext_dup2_exec (operands[0], operands[1], + operands[2], vcc, + operands[3], operands[4])); + DONE; + }) + (define_insn_and_split "add<mode>3_sext_dup2" [(set (match_operand:V_DI 0 "register_operand" "= v") (plus:V_DI diff --git a/gcc/config/gcn/gcn.c b/gcc/config/gcn/gcn.c index 38b5b98c7c8..39eb8fd283f 100644 --- a/gcc/config/gcn/gcn.c +++ b/gcc/config/gcn/gcn.c @@ -1786,9 +1786,10 @@ gcn_expand_scalar_to_vector_address (machine_mode mode, rtx exec, rtx mem, if (AS_FLAT_P (as)) { + rtx vcc = gen_rtx_REG (DImode, CC_SAVE_REG); + if (REG_P (tmp)) { - rtx vcc = gen_rtx_REG (DImode, CC_SAVE_REG); rtx mem_base_lo = gcn_operand_part (DImode, mem_base, 0); rtx mem_base_hi = gcn_operand_part (DImode, mem_base, 1); rtx tmphi = gcn_operand_part (V64DImode, tmp, 1); @@ -1809,17 +1810,17 @@ gcn_expand_scalar_to_vector_address (machine_mode mode, rtx exec, rtx mem, vcc, vcc, undef_v64si, exec)); } else - emit_insn (gen_addv64di3_zext_dup (tmp, mem_base_lo, tmp)); + emit_insn (gen_addv64di3_vcc_zext_dup (tmp, mem_base_lo, tmp, vcc)); } else { tmp = gen_reg_rtx (V64DImode); if (exec) - emit_insn (gen_addv64di3_zext_dup2_exec (tmp, tmplo, mem_base, - gcn_gen_undef (V64DImode), - exec)); + emit_insn (gen_addv64di3_vcc_zext_dup2_exec + (tmp, tmplo, mem_base, vcc, gcn_gen_undef (V64DImode), + exec)); else - emit_insn (gen_addv64di3_zext_dup2 (tmp, tmplo, mem_base)); + emit_insn (gen_addv64di3_vcc_zext_dup2 (tmp, tmplo, mem_base, vcc)); } new_base = tmp; |