Patchwork [trans-mem] undefined reference to a static cloned function

login
register
mail settings
Submitter Aldy Hernandez
Date June 15, 2010, 2:18 p.m.
Message ID <20100615141842.GA27062@redhat.com>
Download mbox | patch
Permalink /patch/55674/
State New
Headers show

Comments

Aldy Hernandez - June 15, 2010, 2:18 p.m.
Here we have a testcase where the compiler can determine that it only
needs the transactional version of a function, so the original function
is not outputted, however we still dump the clone table entry.  Ooops.

I've put the original check back, since just checking the availability
of the transactional clone will not do.

Committing as obvious.

	* varasm.c (finish_tm_clone_pairs_1): Do not dump entry if the
	original function is not needed.

Patch

Index: testsuite/gcc.dg/tm/20100615.c
===================================================================
--- testsuite/gcc.dg/tm/20100615.c	(revision 0)
+++ testsuite/gcc.dg/tm/20100615.c	(revision 0)
@@ -0,0 +1,42 @@ 
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm -O" } */
+
+/* Since the non TM version of new_node() gets optimized away, it
+   shouldn't appear in the clone table either.  */
+/* { dg-final { scan-assembler-not "clone_table" } } */
+
+#define NULL 0
+extern void *malloc (__SIZE_TYPE__);
+
+__attribute__((transaction_pure))
+void exit(int status);
+
+typedef struct node {
+} node_t;
+
+__attribute__((transaction_safe))
+static node_t *new_node(node_t *next)
+{
+  node_t *node;
+  node = (node_t *)malloc(sizeof(node_t));
+  if (node == NULL) {
+    exit(1);
+  }
+  return NULL;
+}
+
+static node_t *set_new()
+{
+  node_t *min, *max;
+  __transaction [[atomic]] {
+    max = new_node(NULL);
+    min = new_node(max);
+  }
+  return min;
+}
+
+int main(int argc, char **argv)
+{
+  set_new();
+  return 0;
+}
Index: varasm.c
===================================================================
--- varasm.c	(revision 160590)
+++ varasm.c	(working copy)
@@ -5850,6 +5850,7 @@  finish_tm_clone_pairs_1 (void **slot, vo
   bool *switched = (bool *) info;
   tree src = map->base.from;
   tree dst = map->to;
+  struct cgraph_node *src_n = cgraph_node (src);
   struct cgraph_node *dst_n = cgraph_node (dst);
 
   /* The function ipa_tm_create_version() marks the clone as needed if
@@ -5861,6 +5862,11 @@  finish_tm_clone_pairs_1 (void **slot, vo
   if (!dst_n->needed)
     return 1;
 
+  /* This covers the case where we have optimized the original
+     function away, and only access the transactional clone.  */
+  if (!src_n->needed)
+    return 1;
+
   if (!*switched)
     {
       switch_to_section (get_named_section (NULL, ".tm_clone_table", 3));