xref: /minix3/external/bsd/llvm/dist/clang/test/CodeGenCXX/nrvo.cpp (revision f4a2713ac843a11c696ec80c0a5e3e5d80b4d338)
1*f4a2713aSLionel Sambuc // RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -o - %s | FileCheck %s
2*f4a2713aSLionel Sambuc // RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -fcxx-exceptions -fexceptions -o - %s | FileCheck --check-prefix=CHECK-EH %s
3*f4a2713aSLionel Sambuc 
4*f4a2713aSLionel Sambuc // Test code generation for the named return value optimization.
5*f4a2713aSLionel Sambuc class X {
6*f4a2713aSLionel Sambuc public:
7*f4a2713aSLionel Sambuc   X();
8*f4a2713aSLionel Sambuc   X(const X&);
9*f4a2713aSLionel Sambuc   ~X();
10*f4a2713aSLionel Sambuc };
11*f4a2713aSLionel Sambuc 
12*f4a2713aSLionel Sambuc // CHECK-LABEL: define void @_Z5test0v
13*f4a2713aSLionel Sambuc // CHECK-EH-LABEL: define void @_Z5test0v
14*f4a2713aSLionel Sambuc X test0() {
15*f4a2713aSLionel Sambuc   X x;
16*f4a2713aSLionel Sambuc   // CHECK:          call {{.*}} @_ZN1XC1Ev
17*f4a2713aSLionel Sambuc   // CHECK-NEXT:     ret void
18*f4a2713aSLionel Sambuc 
19*f4a2713aSLionel Sambuc   // CHECK-EH:       call {{.*}} @_ZN1XC1Ev
20*f4a2713aSLionel Sambuc   // CHECK-EH-NEXT:  ret void
21*f4a2713aSLionel Sambuc   return x;
22*f4a2713aSLionel Sambuc }
23*f4a2713aSLionel Sambuc 
24*f4a2713aSLionel Sambuc // CHECK-LABEL: define void @_Z5test1b(
25*f4a2713aSLionel Sambuc // CHECK-EH-LABEL: define void @_Z5test1b(
26*f4a2713aSLionel Sambuc X test1(bool B) {
27*f4a2713aSLionel Sambuc   // CHECK:      tail call {{.*}} @_ZN1XC1Ev
28*f4a2713aSLionel Sambuc   // CHECK-NEXT: ret void
29*f4a2713aSLionel Sambuc   X x;
30*f4a2713aSLionel Sambuc   if (B)
31*f4a2713aSLionel Sambuc     return (x);
32*f4a2713aSLionel Sambuc   return x;
33*f4a2713aSLionel Sambuc   // CHECK-EH:      tail call {{.*}} @_ZN1XC1Ev
34*f4a2713aSLionel Sambuc   // CHECK-EH-NEXT: ret void
35*f4a2713aSLionel Sambuc }
36*f4a2713aSLionel Sambuc 
37*f4a2713aSLionel Sambuc // CHECK-LABEL: define void @_Z5test2b
38*f4a2713aSLionel Sambuc // CHECK-EH-LABEL: define void @_Z5test2b
39*f4a2713aSLionel Sambuc X test2(bool B) {
40*f4a2713aSLionel Sambuc   // No NRVO.
41*f4a2713aSLionel Sambuc 
42*f4a2713aSLionel Sambuc   X x;
43*f4a2713aSLionel Sambuc   X y;
44*f4a2713aSLionel Sambuc   if (B)
45*f4a2713aSLionel Sambuc     return y;
46*f4a2713aSLionel Sambuc   return x;
47*f4a2713aSLionel Sambuc 
48*f4a2713aSLionel Sambuc   // CHECK: call {{.*}} @_ZN1XC1Ev
49*f4a2713aSLionel Sambuc   // CHECK-NEXT: call {{.*}} @_ZN1XC1Ev
50*f4a2713aSLionel Sambuc   // CHECK: call {{.*}} @_ZN1XC1ERKS_
51*f4a2713aSLionel Sambuc   // CHECK: call {{.*}} @_ZN1XC1ERKS_
52*f4a2713aSLionel Sambuc   // CHECK: call {{.*}} @_ZN1XD1Ev
53*f4a2713aSLionel Sambuc   // CHECK: call {{.*}} @_ZN1XD1Ev
54*f4a2713aSLionel Sambuc   // CHECK: ret void
55*f4a2713aSLionel Sambuc 
56*f4a2713aSLionel Sambuc   // The block ordering in the -fexceptions IR is unfortunate.
57*f4a2713aSLionel Sambuc 
58*f4a2713aSLionel Sambuc   // CHECK-EH:      call {{.*}} @_ZN1XC1Ev
59*f4a2713aSLionel Sambuc   // CHECK-EH-NEXT: invoke {{.*}} @_ZN1XC1Ev
60*f4a2713aSLionel Sambuc   // -> %invoke.cont, %lpad
61*f4a2713aSLionel Sambuc 
62*f4a2713aSLionel Sambuc   // %invoke.cont:
63*f4a2713aSLionel Sambuc   // CHECK-EH:      br i1
64*f4a2713aSLionel Sambuc   // -> %if.then, %if.end
65*f4a2713aSLionel Sambuc 
66*f4a2713aSLionel Sambuc   // %if.then: returning 'x'
67*f4a2713aSLionel Sambuc   // CHECK-EH:      invoke {{.*}} @_ZN1XC1ERKS_
68*f4a2713aSLionel Sambuc   // -> %cleanup, %lpad1
69*f4a2713aSLionel Sambuc 
70*f4a2713aSLionel Sambuc   // %lpad: landing pad for ctor of 'y', dtor of 'y'
71*f4a2713aSLionel Sambuc   // CHECK-EH:      [[CAUGHTVAL:%.*]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
72*f4a2713aSLionel Sambuc   // CHECK-EH-NEXT:   cleanup
73*f4a2713aSLionel Sambuc   // CHECK-EH-NEXT: extractvalue { i8*, i32 } [[CAUGHTVAL]], 0
74*f4a2713aSLionel Sambuc   // CHECK-EH-NEXT: extractvalue { i8*, i32 } [[CAUGHTVAL]], 1
75*f4a2713aSLionel Sambuc   // CHECK-EH-NEXT: br label
76*f4a2713aSLionel Sambuc   // -> %eh.cleanup
77*f4a2713aSLionel Sambuc 
78*f4a2713aSLionel Sambuc   // %lpad1: landing pad for return copy ctors, EH cleanup for 'y'
79*f4a2713aSLionel Sambuc   // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev
80*f4a2713aSLionel Sambuc   // -> %eh.cleanup, %terminate.lpad
81*f4a2713aSLionel Sambuc 
82*f4a2713aSLionel Sambuc   // %if.end: returning 'y'
83*f4a2713aSLionel Sambuc   // CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_
84*f4a2713aSLionel Sambuc   // -> %cleanup, %lpad1
85*f4a2713aSLionel Sambuc 
86*f4a2713aSLionel Sambuc   // %cleanup: normal cleanup for 'y'
87*f4a2713aSLionel Sambuc   // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev
88*f4a2713aSLionel Sambuc   // -> %invoke.cont11, %lpad
89*f4a2713aSLionel Sambuc 
90*f4a2713aSLionel Sambuc   // %invoke.cont11: normal cleanup for 'x'
91*f4a2713aSLionel Sambuc   // CHECK-EH:      call {{.*}} @_ZN1XD1Ev
92*f4a2713aSLionel Sambuc   // CHECK-EH-NEXT: ret void
93*f4a2713aSLionel Sambuc 
94*f4a2713aSLionel Sambuc   // %eh.cleanup:  EH cleanup for 'x'
95*f4a2713aSLionel Sambuc   // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev
96*f4a2713aSLionel Sambuc   // -> %invoke.cont17, %terminate.lpad
97*f4a2713aSLionel Sambuc 
98*f4a2713aSLionel Sambuc   // %invoke.cont17: rethrow block for %eh.cleanup.
99*f4a2713aSLionel Sambuc   // This really should be elsewhere in the function.
100*f4a2713aSLionel Sambuc   // CHECK-EH:      resume { i8*, i32 }
101*f4a2713aSLionel Sambuc 
102*f4a2713aSLionel Sambuc   // %terminate.lpad: terminate landing pad.
103*f4a2713aSLionel Sambuc   // CHECK-EH:      [[T0:%.*]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
104*f4a2713aSLionel Sambuc   // CHECK-EH-NEXT:   catch i8* null
105*f4a2713aSLionel Sambuc   // CHECK-EH-NEXT: [[T1:%.*]] = extractvalue { i8*, i32 } [[T0]], 0
106*f4a2713aSLionel Sambuc   // CHECK-EH-NEXT: call void @__clang_call_terminate(i8* [[T1]]) [[NR_NUW:#[0-9]+]]
107*f4a2713aSLionel Sambuc   // CHECK-EH-NEXT: unreachable
108*f4a2713aSLionel Sambuc 
109*f4a2713aSLionel Sambuc }
110*f4a2713aSLionel Sambuc 
111*f4a2713aSLionel Sambuc X test3(bool B) {
112*f4a2713aSLionel Sambuc   // FIXME: We don't manage to apply NRVO here, although we could.
113*f4a2713aSLionel Sambuc   {
114*f4a2713aSLionel Sambuc     X y;
115*f4a2713aSLionel Sambuc     return y;
116*f4a2713aSLionel Sambuc   }
117*f4a2713aSLionel Sambuc   X x;
118*f4a2713aSLionel Sambuc   return x;
119*f4a2713aSLionel Sambuc }
120*f4a2713aSLionel Sambuc 
121*f4a2713aSLionel Sambuc extern "C" void exit(int) throw();
122*f4a2713aSLionel Sambuc 
123*f4a2713aSLionel Sambuc // CHECK-LABEL: define void @_Z5test4b
124*f4a2713aSLionel Sambuc X test4(bool B) {
125*f4a2713aSLionel Sambuc   {
126*f4a2713aSLionel Sambuc     // CHECK: tail call {{.*}} @_ZN1XC1Ev
127*f4a2713aSLionel Sambuc     X x;
128*f4a2713aSLionel Sambuc     // CHECK: br i1
129*f4a2713aSLionel Sambuc     if (B)
130*f4a2713aSLionel Sambuc       return x;
131*f4a2713aSLionel Sambuc   }
132*f4a2713aSLionel Sambuc   // CHECK: tail call {{.*}} @_ZN1XD1Ev
133*f4a2713aSLionel Sambuc   // CHECK: tail call void @exit(i32 1)
134*f4a2713aSLionel Sambuc   exit(1);
135*f4a2713aSLionel Sambuc }
136*f4a2713aSLionel Sambuc 
137*f4a2713aSLionel Sambuc #ifdef __EXCEPTIONS
138*f4a2713aSLionel Sambuc // CHECK-EH-LABEL: define void @_Z5test5
139*f4a2713aSLionel Sambuc void may_throw();
140*f4a2713aSLionel Sambuc X test5() {
141*f4a2713aSLionel Sambuc   try {
142*f4a2713aSLionel Sambuc     may_throw();
143*f4a2713aSLionel Sambuc   } catch (X x) {
144*f4a2713aSLionel Sambuc     // CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_
145*f4a2713aSLionel Sambuc     // CHECK-EH: call void @__cxa_end_catch()
146*f4a2713aSLionel Sambuc     // CHECK-EH: ret void
147*f4a2713aSLionel Sambuc     return x;
148*f4a2713aSLionel Sambuc   }
149*f4a2713aSLionel Sambuc }
150*f4a2713aSLionel Sambuc #endif
151*f4a2713aSLionel Sambuc 
152*f4a2713aSLionel Sambuc // rdar://problem/10430868
153*f4a2713aSLionel Sambuc // CHECK-LABEL: define void @_Z5test6v
154*f4a2713aSLionel Sambuc X test6() {
155*f4a2713aSLionel Sambuc   X a __attribute__((aligned(8)));
156*f4a2713aSLionel Sambuc   return a;
157*f4a2713aSLionel Sambuc   // CHECK:      [[A:%.*]] = alloca [[X:%.*]], align 8
158*f4a2713aSLionel Sambuc   // CHECK-NEXT: call {{.*}} @_ZN1XC1Ev([[X]]* [[A]])
159*f4a2713aSLionel Sambuc   // CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_([[X]]* {{%.*}}, [[X]]* [[A]])
160*f4a2713aSLionel Sambuc   // CHECK-NEXT: call {{.*}} @_ZN1XD1Ev([[X]]* [[A]])
161*f4a2713aSLionel Sambuc   // CHECK-NEXT: ret void
162*f4a2713aSLionel Sambuc }
163*f4a2713aSLionel Sambuc 
164*f4a2713aSLionel Sambuc // CHECK-EH: attributes [[NR_NUW]] = { noreturn nounwind }
165