1// RUN: %clang_cc1 -I %S/Inputs -x c++ -std=c++11 -triple x86_64-unknown-linux -emit-llvm -O2 < %s | FileCheck %s
2// RUN: %clang_cc1 -I %S/Inputs -x c++ -std=c++11 -triple x86_64-unknown-linux -emit-llvm -Os < %s | FileCheck %s
3// RUN: %clang_cc1 -I %S/Inputs -x c++ -std=c++11 -triple x86_64-unknown-linux -emit-llvm -Oz < %s | FileCheck %s
4
5#pragma clang optimize off
6
7// This is a macro definition and therefore its text is not present after
8// preprocessing. The pragma has no effect here.
9#define CREATE_FUNC(name)        \
10int name (int param) {           \
11    return param;                \
12}                                \
13
14// This is a declaration and therefore it is not decorated with `optnone`.
15extern int foo(int a, int b);
16// CHECK-DAG: @_Z3fooii{{.*}} [[ATTRFOO:#[0-9]+]]
17
18// This is a definition and therefore it will be decorated with `optnone`.
19int bar(int x, int y) {
20    for(int i = 0; i < x; ++i)
21        y += x;
22    return y + foo(x, y);
23}
24// CHECK-DAG: @_Z3barii{{.*}} [[ATTRBAR:#[0-9]+]]
25
26// The function "int created (int param)" created by the macro invocation
27// is also decorated with the `optnone` attribute because it is within a
28// region of code affected by the functionality (not because of the position
29// of the macro definition).
30CREATE_FUNC (created)
31// CHECK-DAG: @_Z7createdi{{.*}} [[ATTRCREATED:#[0-9]+]]
32
33class MyClass {
34    public:
35        // The declaration of the method is not decorated with `optnone`.
36        int method(int blah);
37};
38
39// The definition of the method instead is decorated with `optnone`.
40int MyClass::method(int blah) {
41    return blah + 1;
42}
43// CHECK-DAG: @_ZN7MyClass6methodEi{{.*}} [[ATTRMETHOD:#[0-9]+]]
44
45// A template declaration will not be decorated with `optnone`.
46template <typename T> T twice (T param);
47
48// The template definition will be decorated with the attribute `optnone`.
49template <typename T> T thrice (T param) {
50    return 3 * param;
51}
52
53// This function definition will not be decorated with `optnone` because the
54// attribute would conflict with `always_inline`.
55int __attribute__((always_inline)) baz(int z) {
56    return foo(z, 2);
57}
58// CHECK-DAG: @_Z3bazi{{.*}} [[ATTRBAZ:#[0-9]+]]
59
60// This function definition will not be decorated with `optnone` because the
61// attribute would conflict with `minsize`.
62int __attribute__((minsize)) bax(int z) {
63    return foo(z, 2);
64}
65// CHECK-DAG: @_Z3baxi{{.*}} [[ATTRBAX:#[0-9]+]]
66
67#pragma clang optimize on
68
69// The function "int wombat(int param)" created by the macro is not
70// decorated with `optnone`, because the pragma applies its effects only
71// after preprocessing. The position of the macro definition is not
72// relevant.
73CREATE_FUNC (wombat)
74// CHECK-DAG: @_Z6wombati{{.*}} [[ATTRWOMBAT:#[0-9]+]]
75
76// This instantiation of the "twice" template function with a "float" type
77// will not have an `optnone` attribute because the template declaration was
78// not affected by the pragma.
79float container (float par) {
80    return twice(par);
81}
82// CHECK-DAG: @_Z9containerf{{.*}} [[ATTRCONTAINER:#[0-9]+]]
83// CHECK-DAG: @_Z5twiceIfET_S0_{{.*}} [[ATTRTWICE:#[0-9]+]]
84
85// This instantiation of the "thrice" template function with a "float" type
86// will have an `optnone` attribute because the template definition was
87// affected by the pragma.
88float container2 (float par) {
89    return thrice(par);
90}
91// CHECK-DAG: @_Z10container2f{{.*}} [[ATTRCONTAINER2:#[0-9]+]]
92// CHECK-DAG: @_Z6thriceIfET_S0_{{.*}} [[ATTRTHRICEFLOAT:#[0-9]+]]
93
94
95// A template specialization is a new definition and it will not be
96// decorated with an `optnone` attribute because it is now outside of the
97// affected region.
98template<> int thrice(int par) {
99    return (par << 1) + par;
100}
101int container3 (int par) {
102    return thrice(par);
103}
104// CHECK-DAG: @_Z10container3i{{.*}} [[ATTRCONTAINER3:#[0-9]+]]
105// CHECK-DAG: @_Z6thriceIiET_S0_{{.*}} [[ATTRTHRICEINT:#[0-9]+]]
106
107
108// Test that we can re-open and re-close an "off" region after the first one,
109// and that this works as expected.
110
111#pragma clang optimize off
112
113int another_optnone(int x) {
114    return x << 1;
115}
116// CHECK-DAG: @_Z15another_optnonei{{.*}} [[ATTRANOTHEROPTNONE:#[0-9]+]]
117
118#pragma clang optimize on
119
120int another_normal(int x) {
121    return x << 2;
122}
123// CHECK-DAG: @_Z14another_normali{{.*}} [[ATTRANOTHERNORMAL:#[0-9]+]]
124
125
126// Test that we can re-open an "off" region by including a header with the
127// pragma and that this works as expected (i.e. the off region "falls through"
128// the end of the header into this file).
129
130#include <header-with-pragma-optimize-off.h>
131
132int yet_another_optnone(int x) {
133    return x << 3;
134}
135// CHECK-DAG: @_Z19yet_another_optnonei{{.*}} [[ATTRYETANOTHEROPTNONE:#[0-9]+]]
136
137#pragma clang optimize on
138
139int yet_another_normal(int x) {
140    return x << 4;
141}
142// CHECK-DAG: @_Z18yet_another_normali{{.*}} [[ATTRYETANOTHERNORMAL:#[0-9]+]]
143
144
145// Check for both noinline and optnone on each function that should have them.
146// CHECK-DAG: attributes [[ATTRBAR]] = { {{.*}}noinline{{.*}}optnone{{.*}} }
147// CHECK-DAG: attributes [[ATTRCREATED]] = { {{.*}}noinline{{.*}}optnone{{.*}} }
148// CHECK-DAG: attributes [[ATTRMETHOD]] = { {{.*}}noinline{{.*}}optnone{{.*}} }
149// CHECK-DAG: attributes [[ATTRTHRICEFLOAT]] = { {{.*}}noinline{{.*}}optnone{{.*}} }
150// CHECK-DAG: attributes [[ATTRANOTHEROPTNONE]] = { {{.*}}noinline{{.*}}optnone{{.*}} }
151// CHECK-DAG: attributes [[ATTRYETANOTHEROPTNONE]] = { {{.*}}noinline{{.*}}optnone{{.*}} }
152
153// Check that the other functions do NOT have optnone.
154// CHECK-DAG-NOT: attributes [[ATTRFOO]] = { {{.*}}optnone{{.*}} }
155// CHECK-DAG-NOT: attributes [[ATTRBAZ]] = { {{.*}}optnone{{.*}} }
156// CHECK-DAG-NOT: attributes [[ATTRBAX]] = { {{.*}}optnone{{.*}} }
157// CHECK-DAG-NOT: attributes [[ATTRWOMBAT]] = { {{.*}}optnone{{.*}} }
158// CHECK-DAG-NOT: attributes [[ATTRCONTAINER]] = { {{.*}}optnone{{.*}} }
159// CHECK-DAG-NOT: attributes [[ATTRTWICE]] = { {{.*}}optnone{{.*}} }
160// CHECK-DAG-NOT: attributes [[ATTRCONTAINER2]] = { {{.*}}optnone{{.*}} }
161// CHECK-DAG-NOT: attributes [[ATTRCONTAINER3]] = { {{.*}}optnone{{.*}} }
162// CHECK-DAG-NOT: attributes [[ATTRTHRICEINT]] = { {{.*}}optnone{{.*}} }
163// CHECK-DAG-NOT: attributes [[ATTRANOTHERNORMAL]] = { {{.*}}optnone{{.*}} }
164// CHECK-DAG-NOT: attributes [[ATTRYETANOTHERNORMAL]] = { {{.*}}optnone{{.*}} }
165