From 596cf08845f5962e29ceae043849dac0469fbbee Mon Sep 17 00:00:00 2001
From: Maxim Kuvyrkov <maxim.kuvyrkov@gmail.com>
Date: Wed, 16 Jan 2013 18:24:26 +1300
Subject: [PATCH] Inlining and devirtualizaion tests 	*
 g++.dg/ipa/inline-devirt-{1235}.C: New tests. 	*
 g++.dg/ipa/inline-devirt-{46789}.C: New tests, xfailed for
 now.

---
 gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-1.C |   54 +++++++++++++
 gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-2.C |   49 +++++++++++
 gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-3.C |   49 +++++++++++
 gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-4.C |   54 +++++++++++++
 gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-5.C |   29 +++++++
 gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-6.C |   34 ++++++++
 gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-7.C |   70 ++++++++++++++++
 gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-8.C |   72 +++++++++++++++++
 gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-9.C |   85 ++++++++++++++++++++
 9 files changed, 496 insertions(+)
 create mode 100644 gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-1.C
 create mode 100644 gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-2.C
 create mode 100644 gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-3.C
 create mode 100644 gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-4.C
 create mode 100644 gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-5.C
 create mode 100644 gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-6.C
 create mode 100644 gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-7.C
 create mode 100644 gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-8.C
 create mode 100644 gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-9.C

diff --git a/gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-1.C b/gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-1.C
new file mode 100644
index 0000000..58b04d0
--- /dev/null
+++ b/gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-1.C
@@ -0,0 +1,54 @@
+/* Verify that the inliner makes good decisions and the example
+   is optimized to 4 printf()s in main().  */
+// { dg-do compile }
+// { dg-options "-O2 -fdump-tree-optimized"  }
+
+#include <stdio.h>
+
+class Calculable
+{
+public:
+	virtual unsigned char calculate() = 0;
+	virtual ~Calculable() {}
+};
+
+class X : public Calculable
+{
+public:
+	unsigned char calculate() { return 1; }
+};
+
+class Y : public Calculable
+{
+public:
+	virtual unsigned char calculate() { return 2; }
+};
+
+static void print(X& c)
+{
+	printf("%d\n", c.calculate());
+	printf("+1: %d\n", c.calculate() + 1);
+}
+
+static void print(Y& c)
+{
+	printf("%d\n", c.calculate());
+	printf("+1: %d\n", c.calculate() + 1);
+}
+
+int main()
+{
+	X x;
+	Y y;
+
+	print(x);
+	print(y);
+
+	return 0;
+}
+
+// { dg-final { scan-tree-dump "printf \\(\"%d\\\\n\", 1\\);" "optimized" } }
+// { dg-final { scan-tree-dump "printf \\(\"\\+1: %d\\\\n\", 2\\);" "optimized" } }
+// { dg-final { scan-tree-dump "printf \\(\"%d\\\\n\", 2\\);" "optimized" } }
+// { dg-final { scan-tree-dump "printf \\(\"\\+1: %d\\\\n\", 3\\);" "optimized" } }
+// { dg-final { cleanup-tree-dump "optimized" } }
diff --git a/gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-2.C b/gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-2.C
new file mode 100644
index 0000000..62add89
--- /dev/null
+++ b/gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-2.C
@@ -0,0 +1,49 @@
+/* Verify that the inliner makes good decisions and the example
+   is optimized to 4 printf()s in main().  */
+// { dg-do compile }
+// { dg-options "-O2 -fdump-tree-optimized"  }
+
+#include <stdio.h>
+
+class Calculable
+{
+public:
+	virtual unsigned char calculate() = 0;
+	virtual ~Calculable() {}
+};
+
+class X : public Calculable
+{
+public:
+	virtual unsigned char calculate() { return 1; }
+};
+
+class Y : public Calculable
+{
+public:
+	unsigned char calculate() { return 2; }
+};
+
+static void print(Calculable& c)
+{
+	printf("%d\n", c.calculate());
+	printf("+1: %d\n", c.calculate() + 1);
+}
+
+int main()
+{
+	X x;
+	Y y;
+
+	print(x);
+	print(y);
+
+	return 0;
+
+}
+
+// { dg-final { scan-tree-dump "printf \\(\"%d\\\\n\", 1\\);" "optimized" } }
+// { dg-final { scan-tree-dump "printf \\(\"\\+1: %d\\\\n\", 2\\);" "optimized" } }
+// { dg-final { scan-tree-dump "printf \\(\"%d\\\\n\", 2\\);" "optimized" } }
+// { dg-final { scan-tree-dump "printf \\(\"\\+1: %d\\\\n\", 3\\);" "optimized" } }
+// { dg-final { cleanup-tree-dump "optimized" } }
diff --git a/gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-3.C b/gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-3.C
new file mode 100644
index 0000000..7e62f01
--- /dev/null
+++ b/gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-3.C
@@ -0,0 +1,49 @@
+/* Verify that the inliner makes good decisions and the example
+   is optimized to 3 printf()s in main().  */
+// { dg-do compile }
+// { dg-options "-O2 -fdump-tree-optimized"  }
+
+#include <stdio.h>
+
+class Calculable
+{
+public:
+	virtual unsigned char calculate() const = 0;
+	virtual ~Calculable() {}
+};
+
+class X : public Calculable
+{
+public:
+	virtual unsigned char calculate() const { return 0; }
+};
+
+class Y : public Calculable
+{
+public:
+	virtual unsigned char calculate() const { return 3; }
+};
+
+static void print(const Calculable& c)
+{
+	for (int i = 0; i < c.calculate(); i++)
+	{
+		printf("%d\n", c.calculate());
+	}
+}
+
+int main()
+{
+	X x;
+	Y y;
+
+	print(x);
+	print(y);
+
+	return 0;
+}
+
+// { dg-final { scan-tree-dump "printf \\(\"%d\\\\n\", 3\\);" "optimized" } }
+// { dg-final { scan-tree-dump "printf \\(\"%d\\\\n\", 3\\);" "optimized" } }
+// { dg-final { scan-tree-dump "printf \\(\"%d\\\\n\", 3\\);" "optimized" } }
+// { dg-final { cleanup-tree-dump "optimized" } }
diff --git a/gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-4.C b/gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-4.C
new file mode 100644
index 0000000..f5857d2
--- /dev/null
+++ b/gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-4.C
@@ -0,0 +1,54 @@
+/* Verify that the inliner makes good decisions and the example
+   is optimized to 2 printf()s in main().  */
+// { dg-do compile }
+// { dg-options "-O2 -fdump-tree-optimized"  }
+
+#include <stdint.h>
+#include <stdio.h>
+
+class String
+{
+public:
+  virtual uint64_t length() const = 0;
+  virtual char get(uint64_t index) const = 0;
+  virtual void set(uint64_t index, char value) = 0;
+  virtual char& operator[] (uint64_t value) = 0;
+  virtual ~String() {};
+};
+
+template<uint64_t size> class FixedString : public String
+{
+private:
+  char contents[size + 1];
+
+public:
+  virtual uint64_t length() const { return size; }
+  virtual char get(uint64_t index) const { return contents[index]; }
+  virtual void set(uint64_t index, char value) { contents[index] = value; }
+  virtual char& operator[] (uint64_t index) { return contents[index]; }
+
+  FixedString() { contents[size] = '\0'; }
+};
+
+void print_length (const String& string)
+{
+  for (uint64_t i = 0; i < string.length(); i++)
+    {
+      printf("%d\n", string.get(i));
+    }
+}
+
+int main()
+{
+  FixedString<2> empty;
+  empty[0] = 'a';
+  empty[1] = 'b';
+
+  print_length(empty);
+
+  return 0;
+}
+
+// { dg-final { scan-tree-dump "printf \\(\"%d\\\\n\", 97\\);" "optimized" { xfail *-*-* } } }
+// { dg-final { scan-tree-dump "printf \\(\"%d\\\\n\", 98\\);" "optimized" { xfail *-*-* } } }
+// { dg-final { cleanup-tree-dump "optimized" } }
diff --git a/gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-5.C b/gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-5.C
new file mode 100644
index 0000000..8acfff1
--- /dev/null
+++ b/gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-5.C
@@ -0,0 +1,29 @@
+/* Verify that the inliner makes good decisions and the example
+   is optimized to 4 printf()s in main().  */
+// { dg-do compile }
+// { dg-options "-O2 -fdump-tree-optimized"  }
+
+#include <stdio.h>
+
+typedef unsigned char(*Calculable)(void);
+typedef Calculable(*CalculateStrategy)(void);
+
+unsigned char one() { return 1; }
+Calculable oneStrategy() { return one; }
+unsigned char two() { return 2; }
+Calculable twoStrategy() { return two; }
+
+int main()
+{
+	printf("%d\n", oneStrategy()());
+	printf("+1: %d\n", oneStrategy()() + 1);
+	printf("%d\n", twoStrategy()());
+	printf("+1: %d\n", twoStrategy()() + 1);
+	return 0;
+}
+
+// { dg-final { scan-tree-dump "printf \\(\"%d\\\\n\", 1\\);" "optimized" } }
+// { dg-final { scan-tree-dump "printf \\(\"\\+1: %d\\\\n\", 2\\);" "optimized" } }
+// { dg-final { scan-tree-dump "printf \\(\"%d\\\\n\", 2\\);" "optimized" } }
+// { dg-final { scan-tree-dump "printf \\(\"\\+1: %d\\\\n\", 3\\);" "optimized" } }
+// { dg-final { cleanup-tree-dump "optimized" } }
diff --git a/gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-6.C b/gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-6.C
new file mode 100644
index 0000000..8549012
--- /dev/null
+++ b/gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-6.C
@@ -0,0 +1,34 @@
+/* Verify that the inliner makes good decisions and the example
+   is optimized to 4 printf()s in main().  */
+// { dg-do compile }
+// { dg-options "-O2 -fdump-tree-optimized"  }
+
+#include <stdio.h>
+
+typedef unsigned char(*Calculable)(void);
+typedef Calculable(*CalculateStrategy)(void);
+
+unsigned char one() { return 1; }
+Calculable oneStrategy() { return one; }
+unsigned char two() { return 2; }
+Calculable twoStrategy() { return two; }
+
+static void print(CalculateStrategy calculateStrategy)
+{
+	printf("%d\n", calculateStrategy()());
+	printf("+1: %d\n", calculateStrategy()() + 1);
+}
+
+int main()
+{
+	print(oneStrategy);
+	print(twoStrategy);
+
+	return 0;
+}
+
+// { dg-final { scan-tree-dump "printf \\(\"%d\\\\n\", 1\\);" "optimized" { xfail *-*-* } } }
+// { dg-final { scan-tree-dump "printf \\(\"\\+1: %d\\\\n\", 2\\);" "optimized" { xfail *-*-* } } }
+// { dg-final { scan-tree-dump "printf \\(\"%d\\\\n\", 2\\);" "optimized" { xfail *-*-* } } }
+// { dg-final { scan-tree-dump "printf \\(\"\\+1: %d\\\\n\", 3\\);" "optimized" { xfail *-*-* } } }
+// { dg-final { cleanup-tree-dump "optimized" } }
diff --git a/gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-7.C b/gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-7.C
new file mode 100644
index 0000000..0343ddd
--- /dev/null
+++ b/gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-7.C
@@ -0,0 +1,70 @@
+/* Verify that the inliner makes good decisions and the example
+   is optimized to 4 printf()s in main().  */
+// { dg-do compile }
+// { dg-options "-O2 -std=c++0x -fdump-tree-optimized"  }
+
+#include <stdio.h>
+
+class Stream
+{
+public:
+	virtual unsigned char read() = 0;
+	virtual ~Stream() {}
+};
+
+class Connection
+{
+public:
+	virtual void open() = 0;
+	virtual void close() = 0;
+	virtual ~Connection() {}
+};
+
+class Socket : public Stream, public Connection
+{
+public:
+	virtual unsigned char read() = 0;
+	virtual void open() = 0;
+	virtual void close() { printf("generic close\n"); }
+};
+
+class LinuxSocket : public Socket
+{
+public:
+	virtual unsigned char read() { return 'l'; }
+	virtual void open() { printf("linux open\n"); }
+};
+
+class CustomSocket : public Socket
+{
+public:
+	virtual unsigned char read() { return 0; }
+	virtual void open() { printf("custom open\n"); }
+	virtual void close() { printf("custom close\n"); }
+};
+
+static void readToEnd(Stream* stream)
+{
+	while (stream->read() == 0) { printf("got it\n"); }
+}
+
+static Socket* createSocket()
+{
+	return new LinuxSocket();
+}
+
+int main()
+{
+	auto socket = createSocket();
+	socket->open();
+	readToEnd(socket);
+	socket->close();
+
+	delete socket;
+
+	return 0;
+}
+
+// { dg-final { scan-tree-dump "__builtin_puts \\(&\"linux open\"\\\[0\\\]\\);\n" "optimized" { xfail *-*-* } } }
+// { dg-final { scan-tree-dump "__builtin_puts \\(&\"generic close\"\\\[0\\\]\\);\n" "optimized" { xfail *-*-* } } }
+// { dg-final { cleanup-tree-dump "optimized" } }
diff --git a/gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-8.C b/gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-8.C
new file mode 100644
index 0000000..dac85cd
--- /dev/null
+++ b/gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-8.C
@@ -0,0 +1,72 @@
+/* Verify that the inliner makes good decisions and the example
+   is optimized to 4 printf()s in main().  */
+// { dg-do compile }
+// { dg-options "-O2 -fdump-tree-optimized"  }
+
+#include <stdio.h>
+
+template<class TOutput, typename TInput> class Factory
+{
+public:
+	virtual TOutput* createFrom(TInput) = 0;
+	virtual ~Factory() {};
+};
+
+class Calculable
+{
+public:
+	virtual unsigned char calculate() = 0;
+	virtual ~Calculable() {};
+};
+
+class X : public Calculable
+{
+public:
+	virtual unsigned char calculate() { return 1; }
+};
+
+class Y : public Calculable
+{
+public:
+	virtual unsigned char calculate() { throw; }
+};
+
+enum Letter
+{
+	LetterX,
+	LetterY
+};
+
+class CalculableFactory : Factory<Calculable, Letter>
+{
+public:
+      virtual Calculable* createFrom(Letter letter)
+      {
+		switch(letter)
+		{
+			case LetterX: return new X();
+			default: return new Y();
+		}
+      }
+};
+
+
+static void print(Calculable* c)
+{
+	printf("+1: %d\n", c->calculate() + 1);
+}
+
+int main()
+{
+	CalculableFactory calcuableFactory;
+	Calculable* calculable = calcuableFactory.createFrom(LetterX);
+
+	print(calculable);
+
+	delete calculable;
+
+	return 0;
+}
+
+// { dg-final { scan-tree-dump "printf \\(\"\\+1: %d\\\\n\", 2\\);" "optimized" { xfail *-*-* } } }
+// { dg-final { cleanup-tree-dump "optimized" } }
diff --git a/gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-9.C b/gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-9.C
new file mode 100644
index 0000000..8334389
--- /dev/null
+++ b/gcc-4_7/gcc/testsuite/g++.dg/ipa/inline-devirt-9.C
@@ -0,0 +1,85 @@
+/* Verify that the inliner makes good decisions and the example
+   is optimized to 1 printf() in main().  */
+// { dg-do compile }
+// { dg-options "-O2 -std=c++0x -fdump-tree-optimized"  }
+
+#include <stdio.h>
+#include <memory>
+
+using namespace std;
+
+template<class TOutput, typename TInput> class Factory
+{
+public:
+	virtual shared_ptr<TOutput> createFrom(TInput) = 0;
+	virtual ~Factory() {};
+};
+
+class Calculable
+{
+public:
+	virtual unsigned char calculate() = 0;
+	virtual ~Calculable() {};
+};
+
+enum LetterType
+{
+	LetterX,
+	LetterY
+};
+
+class Letter
+{
+public:
+	Letter(LetterType type) : _type(type) {}
+	virtual ~Letter() {}
+
+protected:
+	LetterType _type;
+};
+
+class X : public Letter, public Calculable
+{
+public:
+	X() : Letter(LetterX) {}
+	virtual unsigned char calculate() { return 1; }
+};
+
+class Y : public Letter, public Calculable
+{
+public:
+	Y() : Letter(LetterY) {}
+	virtual unsigned char calculate() { throw; }
+};
+
+class CalculableFactory : Factory<Calculable, LetterType>
+{
+public:
+      virtual shared_ptr<Calculable> createFrom(LetterType letter)
+      {
+		switch(letter)
+		{
+			case LetterX: return make_shared<X>();
+			default: return make_shared<Y>();
+		}
+      }
+};
+
+
+static void print(Calculable& c)
+{
+	printf("+1: %d\n", c.calculate() + 1);
+}
+
+int main()
+{
+	CalculableFactory calcuableFactory;
+	auto calculable = calcuableFactory.createFrom(LetterX);
+
+	print(*calculable);
+
+	return 0;
+}
+
+// { dg-final { scan-tree-dump "printf \\(\"\\+1: %d\\\\n\", 2\\);" "optimized" { xfail *-*-* } } }
+// { dg-final { cleanup-tree-dump "optimized" } }
-- 
1.7.9.5

