probinson created this revision.
probinson added a reviewer: aaron.ballman.
probinson added a subscriber: cfe-commits.

Found some tests we wrote back in the day, but which never made it upstream.

optnone-and-attributes.cpp is a more thorough exercise of optnone attribute 
interaction than we have currently.

I'm not entirely sure about the value of optnone-class-members.cpp and 
optnone-templates.cpp as these would seem to be really exercising the main 
attribute handling in the context of classes, inheritance, and template 
instantiation; not really that specific to optnone, but it's hard to tell 
whether general attribute handling tests cover these situations.  I'm happy to 
contribute them, or throw them away.

The tweak to optnone-def-decl.cpp just makes that last CHECK do what we 
actually meant it to.

http://reviews.llvm.org/D15704

Files:
  test/CodeGenCXX/optnone-and-attributes.cpp
  test/CodeGenCXX/optnone-class-members.cpp
  test/CodeGenCXX/optnone-def-decl.cpp
  test/CodeGenCXX/optnone-templates.cpp

Index: test/CodeGenCXX/optnone-templates.cpp
===================================================================
--- test/CodeGenCXX/optnone-templates.cpp
+++ test/CodeGenCXX/optnone-templates.cpp
@@ -0,0 +1,104 @@
+// RUN: %clang_cc1 %s -triple %itanium_abi_triple -std=c++11 -emit-llvm -o - | FileCheck %s
+
+// Test optnone on template instantiations.
+
+//-- Effect of optnone on generic add template function.
+
+template <typename T> T template_normal(T a)
+{
+  return a + a;
+}
+
+template <typename T> __attribute__((optnone)) T template_optnone(T a)
+{
+  return a + a + a;
+}
+
+// This function should cause instantiations of each template, one marked
+// with the 'optnone' attribute.
+int container(int i)
+{
+  return template_normal<int>(i) + template_optnone<int>(i);
+}
+
+// CHECK: @_Z15template_normalIiET_S0_({{.*}}) [[NORMAL:#[0-9]+]]
+// CHECK: @_Z16template_optnoneIiET_S0_({{.*}}) [[OPTNONE:#[0-9]+]]
+
+
+//-- Effect of optnone on a partial specialization.
+//   FIRST TEST: a method becomes marked with optnone in the specialization.
+
+template <typename T, typename U> class template_normal_base {
+public:
+  T method(T t, U u) 
+  {
+    return t + static_cast<T>(u);
+  }
+};
+
+template <typename U> class template_normal_base<int, U>
+{
+public:
+  __attribute__((optnone)) int method (int t, U u)
+  {
+    return t - static_cast<int>(u);
+  }
+};
+
+// This function should cause an instantiation of the full template (whose
+// method is not marked optnone) and an instantiation of the partially
+// specialized template (whose method is marked optnone).
+void container2() 
+{
+  int y = 2;
+  float z = 3.0;
+  template_normal_base<float, int> class_normal;
+  template_normal_base<int, float> class_optnone;
+  float r1 = class_normal.method(z, y);
+  float r2 = class_optnone.method(y, z);
+}
+
+// CHECK: @_ZN20template_normal_baseIfiE6methodEfi({{.*}}) [[NORMAL]]
+// CHECK: @_ZN20template_normal_baseIifE6methodEif({{.*}}) [[OPTNONE]]
+
+
+//-- Effect of optnone on a partial specialization.
+//   SECOND TEST: a method loses optnone in the specialization.
+
+template <typename T, typename U> class template_optnone_base {
+public:
+  __attribute__((optnone)) T method(T t, U u) 
+  {
+    return t + static_cast<T>(u);
+  }
+};
+
+template <typename U> class template_optnone_base<int, U>
+{
+public:
+  int method (int t, U u)
+  {
+    return t - static_cast<int>(u);
+  }
+};
+
+// This function should cause an instantiation of the full template (whose
+// method is marked optnone) and an instantiation of the partially
+// specialized template (whose method is not marked optnone).
+void container3() 
+{
+  int y = 2;
+  float z = 3.0;
+  template_optnone_base<float, int> class_optnone;
+  template_optnone_base<int, float> class_normal;
+  float r1 = class_optnone.method(z, y);
+  float r2 = class_normal.method(y, z);
+}
+
+// CHECK: @_ZN21template_optnone_baseIfiE6methodEfi({{.*}}) [[OPTNONE]]
+// CHECK: @_ZN21template_optnone_baseIifE6methodEif({{.*}}) [[NORMAL]]
+
+
+// CHECK: attributes [[NORMAL]] =
+// CHECK-SAME-NOT: optnone
+// CHECK: attributes [[OPTNONE]] = {{.*}} optnone
Index: test/CodeGenCXX/optnone-def-decl.cpp
===================================================================
--- test/CodeGenCXX/optnone-def-decl.cpp
+++ test/CodeGenCXX/optnone-def-decl.cpp
@@ -90,5 +90,6 @@
 // CHECK: @_Z28forceinline_optnone_functionii({{.*}}) [[OPTNONE]]
 
 // CHECK: attributes [[OPTNONE]] = { noinline nounwind optnone {{.*}} }
-// CHECK: attributes [[NORMAL]] = { nounwind {{.*}} }
-
+// CHECK: attributes [[NORMAL]] =
+// CHECK-SAME-NOT: noinline
+// CHECK-SAME-NOT: optnone
Index: test/CodeGenCXX/optnone-class-members.cpp
===================================================================
--- test/CodeGenCXX/optnone-class-members.cpp
+++ test/CodeGenCXX/optnone-class-members.cpp
@@ -0,0 +1,164 @@
+// RUN: %clang_cc1 < %s -triple %itanium_abi_triple -fms-extensions -emit-llvm -x c++ | FileCheck %s
+
+// Test attribute 'optnone' on methods:
+//  -- member functions;
+//  -- static member functions.
+
+// Verify that all methods of struct A are associated to the same attribute set.
+// The attribute set shall contain attributes 'noinline' and 'optnone'.
+
+struct A {
+  // Definition of an optnone static method.
+  __attribute__((optnone))
+  static int static_optnone_method(int a) {
+    return a + a;
+  }
+  // CHECK: @_ZN1A21static_optnone_methodEi({{.*}}) [[OPTNONE:#[0-9]+]]
+
+  // Definition of an optnone normal method.
+  __attribute__((optnone))
+  int optnone_method(int a) {
+    return a + a + a + a;
+  }
+  // CHECK: @_ZN1A14optnone_methodEi({{.*}}) [[OPTNONE]]
+
+  // Declaration of an optnone method with out-of-line definition
+  // that doesn't say optnone.
+  __attribute__((optnone))
+  int optnone_decl_method(int a);
+
+  // Methods declared without attribute optnone; the definitions will
+  // have attribute optnone, and we verify optnone wins.
+  __forceinline static int static_forceinline_method(int a);
+  __attribute__((always_inline)) int alwaysinline_method(int a);
+  __attribute__((noinline)) int noinline_method(int a);
+  __attribute__((minsize)) int minsize_method(int a);
+};
+
+void foo() {
+  A a;
+  A::static_optnone_method(4);
+  a.optnone_method(14);
+  a.optnone_decl_method(12);
+  A::static_forceinline_method(5);
+  a.alwaysinline_method(5);
+  a.noinline_method(6);
+  a.minsize_method(7);
+}
+
+// No attribute here, should still be on the definition.
+int A::optnone_decl_method(int a) {
+  return a;
+}
+// CHECK: @_ZN1A19optnone_decl_methodEi({{.*}}) [[OPTNONE]]
+
+// optnone implies noinline; therefore attribute noinline is added to
+// the set of function attributes.
+// forceinline is instead translated as 'always_inline'.
+// However 'noinline' wins over 'always_inline' and therefore
+// the resulting attributes for this method are: noinline + optnone
+__attribute__((optnone))
+int A::static_forceinline_method(int a) {
+  return a + a + a + a;
+}
+// CHECK: @_ZN1A25static_forceinline_methodEi({{.*}}) [[OPTNONE]]
+
+__attribute__((optnone))
+int A::alwaysinline_method(int a) {
+  return a + a + a + a;
+}
+// CHECK: @_ZN1A19alwaysinline_methodEi({{.*}}) [[OPTNONE]]
+
+// 'noinline' + 'noinline and optnone' = 'noinline and optnone'
+__attribute__((optnone))
+int A::noinline_method(int a) {
+  return a + a + a + a;
+}
+// CHECK: @_ZN1A15noinline_methodEi({{.*}}) [[OPTNONE]]
+
+// 'optnone' wins over 'minsize'
+__attribute__((optnone))
+int A::minsize_method(int a) {
+  return a + a + a + a;
+}
+// CHECK: @_ZN1A14minsize_methodEi({{.*}}) [[OPTNONE]]
+
+
+// Test attribute 'optnone' on methods:
+//  -- pure virtual functions
+//  -- base virtual and derived virtual
+//  -- base virtual but not derived virtual
+//  -- optnone methods redefined in override
+
+// A method defined in override doesn't inherit the function attributes of the
+// superclass method.
+
+struct B {
+  virtual int pure_virtual(int a) = 0;
+  __attribute__((optnone))
+  virtual int pure_virtual_with_optnone(int a) = 0;
+
+  virtual int base(int a) {
+    return a + a + a + a;
+  }
+
+  __attribute__((optnone))
+  virtual int optnone_base(int a) {
+    return a + a + a + a;
+  }
+
+  __attribute__((optnone))
+  virtual int only_base_virtual(int a) {
+    return a + a;
+  }
+};
+
+struct C : public B {
+  __attribute__((optnone))
+  virtual int pure_virtual(int a) {
+    return a + a + a + a;
+  }
+
+  virtual int pure_virtual_with_optnone(int a) {
+    return a + a + a + a;
+  }
+
+  __attribute__((optnone))
+  virtual int base(int a) {
+    return a + a;
+  }
+
+  virtual int optnone_base(int a) {
+    return a + a;
+  }
+
+  int only_base_virtual(int a) {
+    return a + a + a + a;
+  }
+};
+
+int bar() {
+  C c;
+  int result;
+  result = c.pure_virtual(3);
+  result += c.pure_virtual_with_optnone(2);
+  result += c.base(5);
+  result += c.optnone_base(7);
+  result += c.only_base_virtual(9);
+  return result;
+}
+
+// CHECK: @_ZN1C12pure_virtualEi({{.*}}) {{.*}} [[OPTNONE]]
+// CHECK: @_ZN1C25pure_virtual_with_optnoneEi({{.*}}) {{.*}} [[NORMAL:#[0-9]+]]
+// CHECK: @_ZN1C4baseEi({{.*}}) {{.*}} [[OPTNONE]]
+// CHECK: @_ZN1C12optnone_baseEi({{.*}}) {{.*}} [[NORMAL]]
+// CHECK: @_ZN1C17only_base_virtualEi({{.*}}) {{.*}} [[NORMAL]]
+// CHECK: @_ZN1B4baseEi({{.*}}) {{.*}} [[NORMAL]]
+// CHECK: @_ZN1B12optnone_baseEi({{.*}}) {{.*}} [[OPTNONE]]
+// CHECK: @_ZN1B17only_base_virtualEi({{.*}}) {{.*}} [[OPTNONE]]
+
+
+// CHECK: attributes [[NORMAL]] =
+// CHECK-SAME-NOT: noinline
+// CHECK-SAME-NOT: optnone
+// CHECK: attributes [[OPTNONE]] = {{.*}} noinline {{.*}} optnone
Index: test/CodeGenCXX/optnone-and-attributes.cpp
===================================================================
--- test/CodeGenCXX/optnone-and-attributes.cpp
+++ test/CodeGenCXX/optnone-and-attributes.cpp
@@ -0,0 +1,82 @@
+// RUN: %clang_cc1 < %s -triple i386-mingw32 -fms-extensions -emit-llvm -x c++ | FileCheck %s
+
+// optnone wins over inlinehint.
+// Test that both func1 and func2 are marked optnone and noinline.
+
+// Definition with both optnone and inlinehint.
+__attribute__((optnone))
+inline int func1(int a) {
+  return a + a + a + a;
+}
+// CHECK: @_Z5func1i({{.*}}) [[OPTNONE:#[0-9]+]]
+
+// optnone declaration, inlinehint definition.
+__attribute__((optnone))
+int func2(int a);
+
+inline int func2(int a) {
+  return a + a + a + a;
+}
+// CHECK: @_Z5func2i({{.*}}) [[OPTNONE]]
+
+// Keep alive the definitions of func1 and func2.
+int foo() {
+  int val = func1(1);
+  return val + func2(2);
+}
+
+// optnone wins over minsize.
+__attribute__((optnone))
+int func3(int a);
+
+__attribute__((minsize))
+int func3(int a) {
+  return a + a + a + a;
+}
+// Same attribute set as everything else, therefore no 'minsize'.
+// CHECK: @_Z5func3i({{.*}}) [[OPTNONE]]
+
+
+// Verify that noreturn is compatible with optnone.
+__attribute__((noreturn))
+extern void exit_from_function();
+
+__attribute__((noreturn)) __attribute((optnone))
+extern void noreturn_function(int a) { exit_from_function(); }
+// CHECK: @_Z17noreturn_functioni({{.*}}) [[NORETURN:#[0-9]+]]
+
+
+// Verify that __declspec(noinline) is compatible with optnone.
+__declspec(noinline) __attribute__((optnone))
+void func4() { return; }
+// CHECK: @_Z5func4v() [[OPTNONE]]
+
+__declspec(noinline)
+extern void func5();
+
+__attribute__((optnone))
+void func5() { return; }
+// CHECK: @_Z5func5v() [[OPTNONE]]
+
+
+// Verify also that optnone can be used on dllexport functions.
+// Adding attribute optnone on a dllimport function has no effect.
+
+__attribute__((dllimport))
+__attribute__((optnone))
+int imported_optnone_func(int a);
+
+__attribute__((dllexport))
+__attribute__((optnone))
+int exported_optnone_func(int a) {
+  return imported_optnone_func(a); // use of imported func
+}
+// CHECK: @_Z21exported_optnone_funci({{.*}}) [[OPTNONE]]
+// CHECK: declare dllimport {{.*}} @_Z21imported_optnone_funci({{.*}}) [[DLLIMPORT:#[0-9]+]]
+
+
+// CHECK: attributes [[OPTNONE]] = { noinline {{.*}} optnone
+// CHECK: attributes [[NORETURN]] = { noinline noreturn {{.*}} optnone
+
+// CHECK: attributes [[DLLIMPORT]] =
+// CHECK-SAME-NOT: optnone
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to