nrvo.cpp revision f1549f66a8216a78112286e3978cea2c29d6334c
1// RUN: %clang_cc1 -emit-llvm -O1 -o - %s | FileCheck %s 2// RUN: %clang_cc1 -emit-llvm -O1 -fexceptions -o - %s | FileCheck --check-prefix=CHECK-EH %s 3 4// Test code generation for the named return value optimization. 5class X { 6public: 7 X(); 8 X(const X&); 9 ~X(); 10}; 11 12// CHECK: define void @_Z5test0v 13// CHECK-EH: define void @_Z5test0v 14X test0() { 15 X x; 16 // CHECK: call void @_ZN1XC1Ev 17 // CHECK-NEXT: ret void 18 19 // CHECK-EH: call void @_ZN1XC1Ev 20 // CHECK-EH-NEXT: ret void 21 return x; 22} 23 24// CHECK: define void @_Z5test1b( 25// CHECK-EH: define void @_Z5test1b( 26X test1(bool B) { 27 // CHECK: tail call void @_ZN1XC1Ev 28 // CHECK-NEXT: ret void 29 X x; 30 if (B) 31 return (x); 32 return x; 33 // CHECK-EH: tail call void @_ZN1XC1Ev 34 // CHECK-EH-NEXT: ret void 35} 36 37// CHECK: define void @_Z5test2b 38// CHECK-EH: define void @_Z5test2b 39X test2(bool B) { 40 // No NRVO. 41 42 X x; 43 X y; 44 if (B) 45 return y; 46 return x; 47 48 // CHECK: call void @_ZN1XC1Ev 49 // CHECK-NEXT: call void @_ZN1XC1Ev 50 // CHECK: call void @_ZN1XC1ERKS_ 51 // CHECK: call void @_ZN1XC1ERKS_ 52 // CHECK: call void @_ZN1XD1Ev 53 // CHECK: call void @_ZN1XD1Ev 54 // CHECK: ret void 55 56 // The block ordering in the -fexceptions IR is unfortunate. 57 58 // CHECK-EH: call void @_ZN1XC1Ev 59 // CHECK-EH-NEXT: invoke void @_ZN1XC1Ev 60 // -> %invoke.cont1, %lpad 61 62 // %invoke.cont1: 63 // CHECK-EH: br i1 64 // -> %if.then, %if.end 65 66 // %if.then: returning 'x' 67 // CHECK-EH: invoke void @_ZN1XC1ERKS_ 68 // -> %cleanup, %lpad5 69 70 // %invoke.cont: rethrow block for %eh.cleanup. 71 // This really should be elsewhere in the function. 72 // CHECK-EH: call void @_Unwind_Resume_or_Rethrow 73 // CHECK-EH-NEXT: unreachable 74 75 // %lpad: landing pad for ctor of 'y', dtor of 'y' 76 // CHECK-EH: call i8* @llvm.eh.exception() 77 // CHECK-EH: call i32 (i8*, i8*, ...)* @llvm.eh.selector 78 // CHECK-EH-NEXT: br label 79 // -> %eh.cleanup 80 81 // %invoke.cont2: normal cleanup for 'x' 82 // CHECK-EH: call void @_ZN1XD1Ev 83 // CHECK-EH-NEXT: ret void 84 85 // %lpad5: landing pad for return copy ctors, EH cleanup for 'y' 86 // CHECK-EH: invoke void @_ZN1XD1Ev 87 // -> %eh.cleanup, %terminate.lpad 88 89 // %if.end: returning 'y' 90 // CHECK-EH: invoke void @_ZN1XC1ERKS_ 91 // -> %cleanup, %lpad5 92 93 // %cleanup: normal cleanup for 'y' 94 // CHECK-EH: invoke void @_ZN1XD1Ev 95 // -> %invoke.cont2, %lpad 96 97 // %eh.cleanup: EH cleanup for 'x' 98 // CHECK-EH: invoke void @_ZN1XD1Ev 99 // -> %invoke.cont, %terminate.lpad 100 101 // %terminate.lpad: terminate landing pad. 102 // CHECK-EH: call i8* @llvm.eh.exception() 103 // CHECK-EH-NEXT: call i32 (i8*, i8*, ...)* @llvm.eh.selector 104 // CHECK-EH-NEXT: call void @_ZSt9terminatev() 105 // CHECK-EH-NEXT: unreachable 106 107} 108 109X test3(bool B) { 110 // FIXME: We don't manage to apply NRVO here, although we could. 111 { 112 X y; 113 return y; 114 } 115 X x; 116 return x; 117} 118 119extern "C" void exit(int) throw(); 120 121// CHECK: define void @_Z5test4b 122X test4(bool B) { 123 { 124 // CHECK: tail call void @_ZN1XC1Ev 125 X x; 126 // CHECK: br i1 127 if (B) 128 return x; 129 } 130 // CHECK: tail call void @_ZN1XD1Ev 131 // CHECK: tail call void @exit(i32 1) 132 exit(1); 133} 134