nrvo.cpp revision addd80d1c80d1e9f249988452103c93a564945f0
1// RUN: %clang_cc1 -emit-llvm -O1 -o - %s | FileCheck %s 2// RUN: %clang_cc1 -emit-llvm -O1 -fcxx-exceptions -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.cont, %lpad 61 62 // %invoke.cont: 63 // CHECK-EH: br i1 64 // -> %if.then, %if.end 65 66 // %if.then: returning 'x' 67 // CHECK-EH: invoke void @_ZN1XC1ERKS_ 68 // -> %cleanup, %lpad1 69 70 // %lpad: landing pad for ctor of 'y', dtor of 'y' 71 // CHECK-EH: call i8* @llvm.eh.exception() 72 // CHECK-EH: call i32 (i8*, i8*, ...)* @llvm.eh.selector 73 // CHECK-EH-NEXT: br label 74 // -> %eh.cleanup 75 76 // %lpad1: landing pad for return copy ctors, EH cleanup for 'y' 77 // CHECK-EH: invoke void @_ZN1XD1Ev 78 // -> %eh.cleanup, %terminate.lpad 79 80 // %if.end: returning 'y' 81 // CHECK-EH: invoke void @_ZN1XC1ERKS_ 82 // -> %cleanup, %lpad1 83 84 // %cleanup: normal cleanup for 'y' 85 // CHECK-EH: invoke void @_ZN1XD1Ev 86 // -> %invoke.cont11, %lpad 87 88 // %invoke.cont11: normal cleanup for 'x' 89 // CHECK-EH: call void @_ZN1XD1Ev 90 // CHECK-EH-NEXT: ret void 91 92 // %eh.cleanup: EH cleanup for 'x' 93 // CHECK-EH: invoke void @_ZN1XD1Ev 94 // -> %invoke.cont17, %terminate.lpad 95 96 // %invoke.cont17: rethrow block for %eh.cleanup. 97 // This really should be elsewhere in the function. 98 // CHECK-EH: call void @_Unwind_Resume_or_Rethrow 99 // CHECK-EH-NEXT: unreachable 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 135#ifdef __EXCEPTIONS 136// CHECK-EH: define void @_Z5test5 137void may_throw(); 138X test5() { 139 try { 140 may_throw(); 141 } catch (X x) { 142 // CHECK-EH: invoke void @_ZN1XC1ERKS_ 143 // CHECK-EH: call void @__cxa_end_catch() 144 // CHECK-EH: ret void 145 return x; 146 } 147} 148#endif 149