The main purpose of the aarch64_commit_lazy_save pattern was to defer insertion of a half-diamond until splitting, since splitting knew how to create the associated basic blocks.
However, the fix for PR113220 means that mode-switching also knows how to do that. This patch therefore removes the pattern and emits the subinstructions directly. On its own, this is actually a slight regression, since it means we keep an unnecessary zero { za }. But the cases where that happens are wrong for a different reason, and this patch is a prerequisite to fixing it. Tested on aarch64-linux-gnu & pushed. Richard gcc/ * config/aarch64/aarch64-sme.md (aarch64_commit_lazy_save): Remove, directly inserting the associated sequence * config/aarch64/aarch64.cc (aarch64_mode_emit_local_sme_state): ...here instead. gcc/testsuite/ * gcc.target/aarch64/sme/zt0_state_5.c (test3, test5): Expect zero { za }s. --- gcc/config/aarch64/aarch64-sme.md | 45 ------------------- gcc/config/aarch64/aarch64.cc | 13 ++++-- .../gcc.target/aarch64/sme/zt0_state_5.c | 2 + 3 files changed, 11 insertions(+), 49 deletions(-) diff --git a/gcc/config/aarch64/aarch64-sme.md b/gcc/config/aarch64/aarch64-sme.md index 81d941871ac..c95d4aa696c 100644 --- a/gcc/config/aarch64/aarch64-sme.md +++ b/gcc/config/aarch64/aarch64-sme.md @@ -455,51 +455,6 @@ (define_insn "aarch64_end_private_za_call" [(set_attr "type" "no_insn")] ) -;; This pseudo-instruction is emitted before a private-ZA function uses -;; PSTATE.ZA state for the first time. The instruction checks whether -;; ZA currently contains data belonging to a caller and commits the -;; lazy save if so. -;; -;; Operand 0 is the incoming value of TPIDR2_EL0. Operand 1 is nonzero -;; if ZA is live, and should therefore be zeroed after committing a save. -;; -;; The instruction is generated by the mode-switching pass. It is a -;; define_insn_and_split rather than a define_expand because of the -;; internal control flow. -(define_insn_and_split "aarch64_commit_lazy_save" - [(set (reg:DI ZA_FREE_REGNUM) - (unspec:DI [(match_operand 0 "pmode_register_operand" "r") - (match_operand 1 "const_int_operand") - (reg:DI SME_STATE_REGNUM) - (reg:DI TPIDR2_SETUP_REGNUM) - (reg:VNx16QI ZA_REGNUM)] UNSPEC_COMMIT_LAZY_SAVE)) - (set (reg:DI ZA_REGNUM) - (unspec:DI [(reg:DI SME_STATE_REGNUM) - (reg:DI ZA_FREE_REGNUM)] UNSPEC_INITIAL_ZERO_ZA)) - (clobber (reg:DI R14_REGNUM)) - (clobber (reg:DI R15_REGNUM)) - (clobber (reg:DI R16_REGNUM)) - (clobber (reg:DI R17_REGNUM)) - (clobber (reg:DI R18_REGNUM)) - (clobber (reg:DI R30_REGNUM)) - (clobber (reg:CC CC_REGNUM))] - "" - "#" - "true" - [(const_int 0)] - { - auto label = gen_label_rtx (); - auto jump = emit_jump_insn (gen_aarch64_cbeqdi1 (operands[0], label)); - JUMP_LABEL (jump) = label; - emit_insn (gen_aarch64_tpidr2_save ()); - emit_insn (gen_aarch64_clear_tpidr2 ()); - if (INTVAL (operands[1]) != 0) - emit_insn (gen_aarch64_initial_zero_za ()); - emit_label (label); - DONE; - } -) - ;; ========================================================================= ;; == Loads, stores and moves ;; ========================================================================= diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index 6a39ed8eddf..ed7fbca512b 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -29339,12 +29339,17 @@ aarch64_mode_emit_local_sme_state (aarch64_local_sme_state mode, msr tpidr2_el0, xzr zero { za } // Only if ZA is live no_save: */ - bool is_active = (mode == aarch64_local_sme_state::ACTIVE_LIVE - || mode == aarch64_local_sme_state::ACTIVE_DEAD); auto tmp_reg = gen_reg_rtx (DImode); - auto active_flag = gen_int_mode (is_active, DImode); emit_insn (gen_aarch64_read_tpidr2 (tmp_reg)); - emit_insn (gen_aarch64_commit_lazy_save (tmp_reg, active_flag)); + auto label = gen_label_rtx (); + auto jump = emit_jump_insn (gen_aarch64_cbeqdi1 (tmp_reg, label)); + JUMP_LABEL (jump) = label; + emit_insn (gen_aarch64_tpidr2_save ()); + emit_insn (gen_aarch64_clear_tpidr2 ()); + if (mode == aarch64_local_sme_state::ACTIVE_LIVE + || mode == aarch64_local_sme_state::ACTIVE_DEAD) + emit_insn (gen_aarch64_initial_zero_za ()); + emit_label (label); } if (mode == aarch64_local_sme_state::ACTIVE_LIVE diff --git a/gcc/testsuite/gcc.target/aarch64/sme/zt0_state_5.c b/gcc/testsuite/gcc.target/aarch64/sme/zt0_state_5.c index e18b395476c..0fba21868ed 100644 --- a/gcc/testsuite/gcc.target/aarch64/sme/zt0_state_5.c +++ b/gcc/testsuite/gcc.target/aarch64/sme/zt0_state_5.c @@ -54,6 +54,7 @@ __arm_new("zt0") int test3() ** cbz x0, [^\n]+ ** bl __arm_tpidr2_save ** msr tpidr2_el0, xzr +** zero { za } ** smstart za ** bl in_zt0 ** smstop za @@ -101,6 +102,7 @@ __arm_new("zt0") void test5() ** cbz x0, [^\n]+ ** bl __arm_tpidr2_save ** msr tpidr2_el0, xzr +** zero { za } ** smstart za ** bl out_zt0 ** ... -- 2.25.1