]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
strub: handle volatile promoted args in internal strub [PR112938]
authorAlexandre Oliva <oliva@adacore.com>
Thu, 14 Dec 2023 13:41:13 +0000 (10:41 -0300)
committerAlexandre Oliva <oliva@gnu.org>
Thu, 14 Dec 2023 13:41:13 +0000 (10:41 -0300)
When generating code for an internal strub wrapper, don't clear the
DECL_NOT_GIMPLE_REG_P flag of volatile args, and gimplify them both
before and after any conversion.

While at that, move variable TMP into narrower scopes so that it's
more trivial to track where ARG lives.

for  gcc/ChangeLog

PR middle-end/112938
* ipa-strub.cc (pass_ipa_strub::execute): Handle promoted
volatile args in internal strub.  Simplify.

for  gcc/testsuite/ChangeLog

PR middle-end/112938
* gcc.dg/strub-internal-volatile.c: New.

gcc/ipa-strub.cc
gcc/testsuite/gcc.dg/strub-internal-volatile.c [new file with mode: 0644]

index 8ec6824e8a802fa9753fd7ce45f97293b4c811da..45294b0b46bcb3c0774714aa620e923be3f4ac5f 100644 (file)
@@ -3203,7 +3203,6 @@ pass_ipa_strub::execute (function *)
                   i++, arg = DECL_CHAIN (arg), nparm = DECL_CHAIN (nparm))
                {
                  tree save_arg = arg;
-                 tree tmp = arg;
 
                  /* Arrange to pass indirectly the parms, if we decided to do
                     so, and revert its type in the wrapper.  */
@@ -3211,10 +3210,9 @@ pass_ipa_strub::execute (function *)
                    {
                      tree ref_type = TREE_TYPE (nparm);
                      TREE_ADDRESSABLE (arg) = true;
-                     tree addr = build1 (ADDR_EXPR, ref_type, arg);
-                     tmp = arg = addr;
+                     arg = build1 (ADDR_EXPR, ref_type, arg);
                    }
-                 else
+                 else if (!TREE_THIS_VOLATILE (arg))
                    DECL_NOT_GIMPLE_REG_P (arg) = 0;
 
                  /* Convert the argument back to the type used by the calling
@@ -3223,16 +3221,31 @@ pass_ipa_strub::execute (function *)
                     double to be passed on unchanged to the wrapped
                     function.  */
                  if (TREE_TYPE (nparm) != DECL_ARG_TYPE (nparm))
-                   arg = fold_convert (DECL_ARG_TYPE (nparm), arg);
+                   {
+                     tree tmp = arg;
+                     /* If ARG is e.g. volatile, we must copy and
+                        convert in separate statements.  ???  Should
+                        we drop volatile from the wrapper
+                        instead?  */
+                     if (!is_gimple_val (arg))
+                       {
+                         tmp = create_tmp_reg (TYPE_MAIN_VARIANT
+                                               (TREE_TYPE (arg)), "arg");
+                         gimple *stmt = gimple_build_assign (tmp, arg);
+                         gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
+                       }
+                     arg = fold_convert (DECL_ARG_TYPE (nparm), tmp);
+                   }
 
                  if (!is_gimple_val (arg))
                    {
-                     tmp = create_tmp_reg (TYPE_MAIN_VARIANT
-                                           (TREE_TYPE (arg)), "arg");
+                     tree tmp = create_tmp_reg (TYPE_MAIN_VARIANT
+                                                (TREE_TYPE (arg)), "arg");
                      gimple *stmt = gimple_build_assign (tmp, arg);
                      gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
+                     arg = tmp;
                    }
-                 vargs.quick_push (tmp);
+                 vargs.quick_push (arg);
                  arg = save_arg;
                }
            /* These strub arguments are adjusted later.  */
diff --git a/gcc/testsuite/gcc.dg/strub-internal-volatile.c b/gcc/testsuite/gcc.dg/strub-internal-volatile.c
new file mode 100644 (file)
index 0000000..34d4ec8
--- /dev/null
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target strub } */
+
+void __attribute__ ((strub("internal")))
+f(volatile short s) {
+}
+
+void g(void) {
+  f(0);
+}