[IFUNC}: Properly handle indirect function return

View: New views
3 Messages — Rating Filter:   Alert me  

[IFUNC}: Properly handle indirect function return

by H.J. Lu-10 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,


Indirect function isn't const/pure.  I am checking this patch into
ifunc branch with a testcase.


H.J.
---
Index: testsuite/ChangeLog.ifunc
===================================================================
--- testsuite/ChangeLog.ifunc (revision 149285)
+++ testsuite/ChangeLog.ifunc (working copy)
@@ -1,3 +1,7 @@
+2009-07-06  H.J. Lu  <hongjiu.lu@...>
+
+ * g++.dg/torture/ifunc-26.C: New.
+
 2009-07-05  H.J. Lu  <hongjiu.lu@...>
 
  * g++.dg/torture/ifunc-16.C: Add function name to scan-assembler.
Index: testsuite/g++.dg/torture/ifunc-26.C
===================================================================
--- testsuite/g++.dg/torture/ifunc-26.C (revision 0)
+++ testsuite/g++.dg/torture/ifunc-26.C (revision 0)
@@ -0,0 +1,51 @@
+/* { dg-do compile { target i?86-*-linux* x86_64-*-linux* } } */
+/* { dg-options "-Wall -Wextra" } */
+
+template <class T1, class T2>
+class ifunc
+{
+private:
+  void foo1 (T1);
+  void foo1 (T2);
+
+public:
+  void foo (T1);
+  void foo (T2);
+};
+
+template <class T1, class T2>
+void
+__attribute__ ((ifunc))
+ifunc<T1, T2>::foo (T1)
+{
+  return &ifunc<T1, T2>::foo1;
+}
+
+template <class T1, class T2>
+void
+__attribute__ ((ifunc))
+ifunc<T1, T2>::foo (T2)
+{
+  return &ifunc<T1, T2>::foo1;
+}
+
+void
+bar (int x)
+{
+  ifunc<int, float> i;
+  i.foo (x);
+}
+
+void
+bar (float x)
+{
+  ifunc<int, float> i;
+  i.foo (x);
+}
+
+/* { dg-final { scan-assembler-not ".type\[ \]\+_ZN5ifuncIifE3fooEf, .function" } } */
+/* { dg-final { scan-assembler-not ".type\[ \]\+_ZN5ifuncIifE3fooEi, .function" } } */
+/* { dg-final { scan-assembler "(call|jmp)\[ \]\+_ZN5ifuncIifE3fooEi" } } */
+/* { dg-final { scan-assembler "(call|jmp)\[ \]\+_ZN5ifuncIifE3fooEf" } } */
+/* { dg-final { scan-assembler ".type\[ \]\+_ZN5ifuncIifE3fooEi, .gnu_indirect_function" } } */
+/* { dg-final { scan-assembler ".type\[ \]\+_ZN5ifuncIifE3fooEf, .gnu_indirect_function" } } */
Index: ipa-pure-const.c
===================================================================
--- ipa-pure-const.c (revision 149285)
+++ ipa-pure-const.c (working copy)
@@ -471,6 +471,14 @@ check_stmt (gimple_stmt_iterator *gsip,
           local->looping = true;
  }
       return;
+    case GIMPLE_RETURN:
+      if (DECL_IS_IFUNC (current_function_decl))
+ {
+  if (dump_file)
+    fprintf (dump_file, "    Indirect function is not const/pure");
+  local->pure_const_state = IPA_NEITHER;
+ }
+      break;
     default:
       break;
     }
Index: ChangeLog.ifunc
===================================================================
--- ChangeLog.ifunc (revision 149285)
+++ ChangeLog.ifunc (working copy)
@@ -1,3 +1,8 @@
+2009-07-06  H.J. Lu  <hongjiu.lu@...>
+
+ * ipa-pure-const.c (check_stmt): Properly handle indirect function
+ return.
+
 2009-06-28  H.J. Lu  <hongjiu.lu@...>
 
  * doc/extend.texi: Update ifunc attribute document.

Re: [IFUNC}: Properly handle indirect function return

by Andrew Pinski-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Mon, Jul 6, 2009 at 12:36 PM, H.J. Lu<hongjiu.lu@...> wrote:
> Hi,
> +    case GIMPLE_RETURN:
> +      if (DECL_IS_IFUNC (current_function_decl))
> +       {
> +         if (dump_file)
> +           fprintf (dump_file, "    Indirect function is not const/pure");
> +         local->pure_const_state = IPA_NEITHER;
> +       }
> +      break;

This seems like the incorrect place to put this check as it does not
depend on the return statement.  It seems like it is better if it is
put analyze_function and then skip the walk of the IR.

Thanks,
Andrew Pinski

Re: [IFUNC}: Properly handle indirect function return

by H.J. Lu-30 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Mon, Jul 6, 2009 at 12:41 PM, Andrew Pinski<pinskia@...> wrote:

> On Mon, Jul 6, 2009 at 12:36 PM, H.J. Lu<hongjiu.lu@...> wrote:
>> Hi,
>> +    case GIMPLE_RETURN:
>> +      if (DECL_IS_IFUNC (current_function_decl))
>> +       {
>> +         if (dump_file)
>> +           fprintf (dump_file, "    Indirect function is not const/pure");
>> +         local->pure_const_state = IPA_NEITHER;
>> +       }
>> +      break;
>
> This seems like the incorrect place to put this check as it does not
> depend on the return statement.  It seems like it is better if it is
> put analyze_function and then skip the walk of the IR.
>

I checked in this patch to do this.

Thanks.


H.J.
---
Index: ipa-pure-const.c
===================================================================
--- ipa-pure-const.c (revision 149294)
+++ ipa-pure-const.c (working copy)
@@ -471,14 +471,6 @@ check_stmt (gimple_stmt_iterator *gsip,
           local->looping = true;
  }
       return;
-    case GIMPLE_RETURN:
-      if (DECL_IS_IFUNC (current_function_decl))
- {
-  if (dump_file)
-    fprintf (dump_file, "    Indirect function is not const/pure");
-  local->pure_const_state = IPA_NEITHER;
- }
-      break;
     default:
       break;
     }
@@ -492,7 +484,7 @@ static funct_state
 analyze_function (struct cgraph_node *fn, bool ipa)
 {
   tree decl = fn->decl;
-  tree old_decl = current_function_decl;
+  tree old_decl;
   funct_state l;
   basic_block this_block;

@@ -504,11 +496,17 @@ analyze_function (struct cgraph_node *fn
     }

   l = XCNEW (struct funct_state_d);
-  l->pure_const_state = IPA_CONST;
   l->state_previously_known = IPA_NEITHER;
   l->looping_previously_known = true;
   l->looping = false;
   l->can_throw = false;
+  if (DECL_IS_IFUNC (decl))
+    {
+      l->pure_const_state = IPA_NEITHER;
+      goto skip;
+    }
+  else
+    l->pure_const_state = IPA_CONST;

   if (dump_file)
     {
@@ -516,6 +514,7 @@ analyze_function (struct cgraph_node *fn
        cgraph_node_name (fn));
     }

+  old_decl = current_function_decl;
   push_cfun (DECL_STRUCT_FUNCTION (decl));
   current_function_decl = decl;

@@ -595,6 +594,8 @@ end:

   pop_cfun ();
   current_function_decl = old_decl;
+
+skip:
   if (dump_file)
     {
       if (l->looping)
Index: ChangeLog.ifunc
===================================================================
--- ChangeLog.ifunc (revision 149294)
+++ ChangeLog.ifunc (working copy)
@@ -1,5 +1,10 @@
 2009-07-06  H.J. Lu  <hongjiu.lu@...>

+ * ipa-pure-const.c (check_stmt): Revert the last change.
+ (analyze_function):  Skip analysis for indirect function.
+
+2009-07-06  H.J. Lu  <hongjiu.lu@...>
+
  * ipa-pure-const.c (check_stmt): Properly handle indirect function
  return.



--
H.J.