diff mbox

Function Multiversioning Bug, checking for function versions

Message ID CAAs8Hmy97t6Pc_RNCvhiW8y3-zU9jr8xFccNZ=69hToQ19wkKg@mail.gmail.com
State New
Headers show

Commit Message

Sriraman Tallam Nov. 15, 2012, 10:08 p.m. UTC
Hi,

   Currently, function multiversioning determines that two functions
are different by comparing the arch type and isa flags that are set
after the target string is processed. This leads to cases where  the
versions become identical when the command-line target options are
altered.

For example, these two versions:

__attribute__ target (("sse4.2")))
int foo ()
{
}

__attribute__ target (("popcnt")))
int foo ()
{
}

become identical when -mpopcnt and -msse4.2 are used while building,
leading to build errors.

To avoid this, I have modified the function version determination to
just compare the target string.
Patch attached. Is this alright to submit?

Thanks,
-Sri.
* config/i386/i386.c (ix86_function_versions): Use target string
	to check for function versions instead of target flags.
diff mbox

Patch

Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c	(revision 193486)
+++ config/i386/i386.c	(working copy)
@@ -28646,47 +28646,6 @@  dispatch_function_versions (tree dispatch_decl,
   return 0;
 }
 
-/* This function returns true if FN1 and FN2 are versions of the same function,
-   that is, the targets of the function decls are different.  This assumes
-   that FN1 and FN2 have the same signature.  */
-
-static bool
-ix86_function_versions (tree fn1, tree fn2)
-{
-  tree attr1, attr2;
-  struct cl_target_option *target1, *target2;
-
-  if (TREE_CODE (fn1) != FUNCTION_DECL
-      || TREE_CODE (fn2) != FUNCTION_DECL)
-    return false;
-
-  attr1 = DECL_FUNCTION_SPECIFIC_TARGET (fn1);
-  attr2 = DECL_FUNCTION_SPECIFIC_TARGET (fn2);
-
-  /* Atleast one function decl should have target attribute specified.  */
-  if (attr1 == NULL_TREE && attr2 == NULL_TREE)
-    return false;
-
-  if (attr1 == NULL_TREE)
-    attr1 = target_option_default_node;
-  else if (attr2 == NULL_TREE)
-    attr2 = target_option_default_node;
-
-  target1 = TREE_TARGET_OPTION (attr1);
-  target2 = TREE_TARGET_OPTION (attr2);
-
-  /* target1 and target2 must be different in some way.  */
-  if (target1->x_ix86_isa_flags == target2->x_ix86_isa_flags
-      && target1->x_target_flags == target2->x_target_flags
-      && target1->arch == target2->arch
-      && target1->tune == target2->tune
-      && target1->x_ix86_fpmath == target2->x_ix86_fpmath
-      && target1->branch_cost == target2->branch_cost)
-    return false;
-
-  return true;
-}
-
 /* Comparator function to be used in qsort routine to sort attribute
    specification strings to "target".  */
 
@@ -28799,6 +28758,52 @@  ix86_mangle_function_version_assembler_name (tree
   return get_identifier (assembler_name);
 }
 
+/* This function returns true if FN1 and FN2 are versions of the same function,
+   that is, the target strings of the function decls are different.  This assumes
+   that FN1 and FN2 have the same signature.  */
+
+static bool
+ix86_function_versions (tree fn1, tree fn2)
+{
+  tree attr1, attr2;
+  const char *attr_str1, *attr_str2;
+  char *target1, *target2;
+  bool result;
+  
+  if (TREE_CODE (fn1) != FUNCTION_DECL
+      || TREE_CODE (fn2) != FUNCTION_DECL)
+    return false;
+
+  attr1 = lookup_attribute ("target", DECL_ATTRIBUTES (fn1));
+  attr2 = lookup_attribute ("target", DECL_ATTRIBUTES (fn2));
+
+  /* Atleast one function decl should have the target attribute specified.  */
+  if (attr1 == NULL_TREE && attr2 == NULL_TREE)
+    return false;
+
+  /* If one function does not have a target attribute, these are versions.  */
+  if (attr1 == NULL_TREE || attr2 == NULL_TREE)
+    return true;
+
+  attr_str1 =  TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr1)));
+  attr_str2 =  TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr2)));
+
+  target1 = sorted_attr_string (attr_str1);
+  target2 = sorted_attr_string (attr_str2);
+
+  /* The sorted target strings must be different for fn1 and fn2
+     to be versions.  */
+  if (strcmp (target1, target2) == 0)
+    result = false;
+  else
+    result = true;
+
+  free (target1);
+  free (target2); 
+  
+  return result;
+}
+
 static tree 
 ix86_mangle_decl_assembler_name (tree decl, tree id)
 {