1// { dg-do compile }
2// { dg-options "-fgnu-tm -O2 -fdump-tree-optimized" }
3
4typedef __SIZE_TYPE__ size_t;
5extern void *malloc(size_t);
6
7namespace bench
8{
9    class LLNode
10    {
11    	LLNode* next;
12    	int data;
13
14    public:
15	__attribute__((transaction_safe))
16	LLNode(int val, LLNode* m_next)
17	{
18		data = val;
19		next = m_next;
20	}
21	__attribute__((transaction_safe))
22	  ~LLNode(){}
23	__attribute__((transaction_safe))
24	  int get_val()  {return data;}
25	__attribute__((transaction_safe))
26	  LLNode* get_next()  {return next;}
27	__attribute__((transaction_safe))
28	  void set_val(int val) {data = val;}
29	__attribute__((transaction_safe))
30	  void set_next(LLNode* n)  {next = n;}
31	__attribute__((transaction_safe))
32	  void *operator new(size_t size);
33    };
34
35    class LinkedList
36    {
37      LLNode* head;
38    public:
39	LinkedList();
40	void insert(int val);
41    };
42}
43
44using bench::LinkedList;
45using bench::LLNode;
46
47
48__attribute__((transaction_safe))
49void* LLNode::operator new(size_t size)
50{
51  return malloc(size);
52}
53
54LinkedList::LinkedList() : head(new LLNode(-1, 0)) { }
55
56void LinkedList::insert(int val)
57{
58  __transaction_atomic {
59    LLNode* prev = head;
60    LLNode* curr = head->get_next();
61
62    while (curr != 0) {
63      if (curr->get_val() >= val)
64	break;
65      prev = curr;
66      curr = prev->get_next();
67    }
68
69    if (!curr || (curr->get_val() > val)){
70      LLNode* tmp = new LLNode(val,curr);
71      prev->set_next(tmp);
72    }
73  }
74}
75
76// Make sure we don't do tail optimization on the commit, except on
77// the uninstrumented code path.
78// { dg-final { scan-tree-dump-times "commitTransaction...; .tail call" 1 "optimized" } }
79// { dg-final { cleanup-tree-dump "optimized" } }
80
81