summaryrefslogtreecommitdiff
path: root/0145-Backport-SME-rtl-Try-to-remove-EH-edges-after-pro-ep.patch
diff options
context:
space:
mode:
Diffstat (limited to '0145-Backport-SME-rtl-Try-to-remove-EH-edges-after-pro-ep.patch')
-rw-r--r--0145-Backport-SME-rtl-Try-to-remove-EH-edges-after-pro-ep.patch232
1 files changed, 232 insertions, 0 deletions
diff --git a/0145-Backport-SME-rtl-Try-to-remove-EH-edges-after-pro-ep.patch b/0145-Backport-SME-rtl-Try-to-remove-EH-edges-after-pro-ep.patch
new file mode 100644
index 0000000..cdaf6ee
--- /dev/null
+++ b/0145-Backport-SME-rtl-Try-to-remove-EH-edges-after-pro-ep.patch
@@ -0,0 +1,232 @@
+From 60612cbd9cdd9b5079c0505b9d53c9cd98fba4b1 Mon Sep 17 00:00:00 2001
+From: Kewen Lin <linkw@linux.ibm.com>
+Date: Tue, 15 Nov 2022 20:26:07 -0600
+Subject: [PATCH 046/157] [Backport][SME] rtl: Try to remove EH edges after
+ {pro,epi}logue generation [PR90259]
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=63e1b2e767a3f4695373c2406ff719c0a60c1858
+
+After prologue and epilogue generation, the judgement on whether
+one memory access onto stack frame may trap or not could change,
+since we get more exact stack information by now.
+
+As PR90259 shows, some memory access becomes impossible to trap
+any more after prologue and epilogue generation, it can make
+subsequent optimization be able to remove it if safe, but it
+results in unexpected control flow status due to REG_EH_REGION
+note missing.
+
+This patch proposes to try to remove EH edges with function
+purge_all_dead_edges after prologue and epilogue generation,
+it simplifies CFG as early as we can and don't need any fixup
+in downstream passes.
+
+CFG simplification result with PR90259's case as example:
+
+*before*
+
+ 18: %1:TF=call [`__gcc_qdiv'] argc:0
+ REG_EH_REGION 0x2
+ 77: NOTE_INSN_BASIC_BLOCK 3
+ 19: NOTE_INSN_DELETED
+ 20: NOTE_INSN_DELETED
+ 110: [%31:SI+0x20]=%1:DF
+ REG_EH_REGION 0x2
+ 116: NOTE_INSN_BASIC_BLOCK 4
+ 111: [%31:SI+0x28]=%2:DF
+ REG_EH_REGION 0x2
+ 22: NOTE_INSN_BASIC_BLOCK 5
+ 108: %0:DF=[%31:SI+0x20]
+ REG_EH_REGION 0x2
+ 117: NOTE_INSN_BASIC_BLOCK 6
+ 109: %1:DF=[%31:SI+0x28]
+ REG_EH_REGION 0x2
+ 79: NOTE_INSN_BASIC_BLOCK 7
+ 26: [%31:SI+0x18]=%0:DF
+ 104: pc=L69
+ 105: barrier
+
+*after*
+
+ 18: %1:TF=call [`__gcc_qdiv'] argc:0
+ REG_EH_REGION 0x2
+ 77: NOTE_INSN_BASIC_BLOCK 3
+ 19: NOTE_INSN_DELETED
+ 20: NOTE_INSN_DELETED
+ 110: [%31:SI+0x20]=%1:DF
+ 111: [%31:SI+0x28]=%2:DF
+ 108: %0:DF=[%31:SI+0x20]
+ 109: %1:DF=[%31:SI+0x28]
+ 26: [%31:SI+0x18]=%0:DF
+ 104: pc=L69
+ 105: barrier
+
+ PR rtl-optimization/90259
+
+gcc/ChangeLog:
+
+ * function.cc (rest_of_handle_thread_prologue_and_epilogue): Add
+ parameter fun, and call function purge_all_dead_edges.
+ (pass_thread_prologue_and_epilogue::execute): Name unamed parameter
+ as fun, and use it for rest_of_handle_thread_prologue_and_epilogue.
+
+gcc/testsuite/ChangeLog:
+
+ * g++.target/powerpc/pr90259.C: New.
+---
+ gcc/function.cc | 13 ++-
+ gcc/testsuite/g++.target/powerpc/pr90259.C | 103 +++++++++++++++++++++
+ 2 files changed, 113 insertions(+), 3 deletions(-)
+ create mode 100644 gcc/testsuite/g++.target/powerpc/pr90259.C
+
+diff --git a/gcc/function.cc b/gcc/function.cc
+index 49c7ccf4b..28de39dd6 100644
+--- a/gcc/function.cc
++++ b/gcc/function.cc
+@@ -6529,7 +6529,7 @@ make_pass_leaf_regs (gcc::context *ctxt)
+ }
+
+ static unsigned int
+-rest_of_handle_thread_prologue_and_epilogue (void)
++rest_of_handle_thread_prologue_and_epilogue (function *fun)
+ {
+ /* prepare_shrink_wrap is sensitive to the block structure of the control
+ flow graph, so clean it up first. */
+@@ -6546,6 +6546,13 @@ rest_of_handle_thread_prologue_and_epilogue (void)
+ Fix that up. */
+ fixup_partitions ();
+
++ /* After prologue and epilogue generation, the judgement on whether
++ one memory access onto stack frame may trap or not could change,
++ since we get more exact stack information by now. So try to
++ remove any EH edges here, see PR90259. */
++ if (fun->can_throw_non_call_exceptions)
++ purge_all_dead_edges ();
++
+ /* Shrink-wrapping can result in unreachable edges in the epilogue,
+ see PR57320. */
+ cleanup_cfg (optimize ? CLEANUP_EXPENSIVE : 0);
+@@ -6614,9 +6621,9 @@ public:
+ {}
+
+ /* opt_pass methods: */
+- virtual unsigned int execute (function *)
++ unsigned int execute (function * fun) final override
+ {
+- return rest_of_handle_thread_prologue_and_epilogue ();
++ return rest_of_handle_thread_prologue_and_epilogue (fun);
+ }
+
+ }; // class pass_thread_prologue_and_epilogue
+diff --git a/gcc/testsuite/g++.target/powerpc/pr90259.C b/gcc/testsuite/g++.target/powerpc/pr90259.C
+new file mode 100644
+index 000000000..db75ac7fe
+--- /dev/null
++++ b/gcc/testsuite/g++.target/powerpc/pr90259.C
+@@ -0,0 +1,103 @@
++/* { dg-require-effective-target long_double_ibm128 } */
++/* { dg-options "-O2 -ffloat-store -fgcse -fnon-call-exceptions -fno-forward-propagate -fno-omit-frame-pointer -fstack-protector-all" } */
++/* { dg-add-options long_double_ibm128 } */
++
++/* Verify there is no ICE. */
++
++template <int a> struct b
++{
++ static constexpr int c = a;
++};
++template <bool a> using d = b<a>;
++struct e
++{
++ int f;
++ int
++ g ()
++ {
++ return __builtin_ceil (f / (long double) h);
++ }
++ float h;
++};
++template <typename, typename> using k = d<!bool ()>;
++template <typename> class n
++{
++public:
++ e ae;
++ void af ();
++};
++template <typename l>
++void
++n<l>::af ()
++{
++ ae.g ();
++}
++template <bool> using m = int;
++template <typename ag, typename ah, typename ai = m<k<ag, ah>::c>>
++using aj = n<ai>;
++struct o
++{
++ void
++ af ()
++ {
++ al.af ();
++ }
++ aj<int, int> al;
++};
++template <typename> class am;
++template <typename i> class ao
++{
++protected:
++ static i *ap (int);
++};
++template <typename, typename> class p;
++template <typename ar, typename i, typename... j> class p<ar (j...), i> : ao<i>
++{
++public:
++ static ar
++ as (const int &p1, j...)
++ {
++ (*ao<i>::ap (p1)) (j ()...);
++ }
++};
++template <typename ar, typename... j> class am<ar (j...)>
++{
++ template <typename, typename> using av = int;
++
++public:
++ template <typename i, typename = av<d<!bool ()>, void>,
++ typename = av<i, void>>
++ am (i);
++ using aw = ar (*) (const int &, j...);
++ aw ax;
++};
++template <typename ar, typename... j>
++template <typename i, typename, typename>
++am<ar (j...)>::am (i)
++{
++ ax = p<ar (j...), i>::as;
++}
++struct G
++{
++ void ba (am<void (o)>);
++};
++struct q
++{
++ q ()
++ {
++ G a;
++ a.ba (r ());
++ }
++ struct r
++ {
++ void
++ operator() (o p1)
++ try
++ {
++ p1.af ();
++ }
++ catch (int)
++ {
++ }
++ };
++} s;
+--
+2.33.0
+