teak-llvm/clang/test/CodeGenCXX/nrvo.cpp
Eric Christopher fd39b1bb20 Revert "Revert "As a follow-up to my initial mail to llvm-dev here's a first pass at the O1 described there.""
This reapplies: 8ff85ed905

Original commit message:

As a follow-up to my initial mail to llvm-dev here's a first pass at the O1 described there.

This change doesn't include any change to move from selection dag to fast isel
and that will come with other numbers that should help inform that decision.
There also haven't been any real debuggability studies with this pipeline yet,
this is just the initial start done so that people could see it and we could start
tweaking after.

Test updates: Outside of the newpm tests most of the updates are coming from either
optimization passes not run anymore (and without a compelling argument at the moment)
that were largely used for canonicalization in clang.

Original post:

http://lists.llvm.org/pipermail/llvm-dev/2019-April/131494.html

Tags: #llvm
Differential Revision: https://reviews.llvm.org/D65410

This reverts commit c9ddb02659.
2019-11-26 20:28:52 -08:00

224 lines
6.0 KiB
C++

// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -fno-experimental-new-pass-manager -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -fno-experimental-new-pass-manager -fcxx-exceptions -fexceptions -std=c++03 -o - %s | FileCheck --check-prefixes=CHECK-EH,CHECK-EH-03 %s
// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -fno-experimental-new-pass-manager -fcxx-exceptions -fexceptions -std=c++11 -o - %s | FileCheck --check-prefixes=CHECK-EH,CHECK-EH-11 %s
// Test code generation for the named return value optimization.
class X {
public:
X();
X(const X&);
~X();
};
template<typename T> struct Y {
Y();
static Y f() {
Y y;
return y;
}
};
// CHECK-LABEL: define void @_Z5test0v
// CHECK-EH-LABEL: define void @_Z5test0v
X test0() {
X x;
// CHECK: call {{.*}} @_ZN1XC1Ev
// CHECK-NEXT: ret void
// CHECK-EH: call {{.*}} @_ZN1XC1Ev
// CHECK-EH-NEXT: ret void
return x;
}
// CHECK-LABEL: define void @_Z5test1b(
// CHECK-EH-LABEL: define void @_Z5test1b(
X test1(bool B) {
// CHECK: call {{.*}} @_ZN1XC1Ev
// CHECK-NEXT: ret void
X x;
if (B)
return (x);
return x;
// CHECK-EH: call {{.*}} @_ZN1XC1Ev
// CHECK-EH-NEXT: ret void
}
// CHECK-LABEL: define void @_Z5test2b
// CHECK-EH-LABEL: define void @_Z5test2b
// CHECK-EH-SAME: personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
X test2(bool B) {
// No NRVO.
X x;
X y;
if (B)
return y;
return x;
// CHECK: call {{.*}} @_ZN1XC1Ev
// CHECK-NEXT: {{.*}} getelementptr inbounds %class.X, %class.X* %y, i32 0, i32 0
// CHECK-NEXT: call void @llvm.lifetime.start
// CHECK-NEXT: call {{.*}} @_ZN1XC1Ev
// CHECK: call {{.*}} @_ZN1XC1ERKS_
// CHECK: call {{.*}} @_ZN1XD1Ev
// CHECK-NEXT: call void @llvm.lifetime.end
// CHECK: call {{.*}} @_ZN1XD1Ev
// CHECK-NEXT: call void @llvm.lifetime.end
// CHECK: ret void
// The block ordering in the -fexceptions IR is unfortunate.
// CHECK-EH: call void @llvm.lifetime.start
// CHECK-EH-NEXT: call {{.*}} @_ZN1XC1Ev
// CHECK-EH: call void @llvm.lifetime.start
// CHECK-EH-NEXT: invoke {{.*}} @_ZN1XC1Ev
// -> %invoke.cont, %lpad
// %invoke.cont:
// CHECK-EH: br i1
// -> %if.then, %if.end
// %if.then: returning 'x'
// CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_
// -> %cleanup, %lpad1
// %lpad: landing pad for ctor of 'y', dtor of 'y'
// CHECK-EH: [[CAUGHTVAL:%.*]] = landingpad { i8*, i32 }
// CHECK-EH-NEXT: cleanup
// CHECK-EH-NEXT: extractvalue { i8*, i32 } [[CAUGHTVAL]], 0
// CHECK-EH-NEXT: extractvalue { i8*, i32 } [[CAUGHTVAL]], 1
// CHECK-EH-NEXT: br label
// -> %eh.cleanup
// %lpad1: landing pad for return copy ctors, EH cleanup for 'y'
// CHECK-EH-03: invoke {{.*}} @_ZN1XD1Ev
// -> %eh.cleanup, %terminate.lpad
// CHECK-EH-11: call {{.*}} @_ZN1XD1Ev
// %if.end: returning 'y'
// CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_
// -> %cleanup, %lpad1
// %cleanup: normal cleanup for 'y'
// CHECK-EH-03: invoke {{.*}} @_ZN1XD1Ev
// -> %invoke.cont11, %lpad
// CHECK-EH-11: call {{.*}} @_ZN1XD1Ev
// %invoke.cont11: normal cleanup for 'x'
// CHECK-EH: call void @llvm.lifetime.end
// CHECK-EH-NEXT: call {{.*}} @_ZN1XD1Ev
// CHECK-EH-NEXT: call void @llvm.lifetime.end
// CHECK-EH-NEXT: ret void
// %eh.cleanup: EH cleanup for 'x'
// CHECK-EH-03: invoke {{.*}} @_ZN1XD1Ev
// -> %invoke.cont17, %terminate.lpad
// CHECK-EH-11: call {{.*}} @_ZN1XD1Ev
// %invoke.cont17: rethrow block for %eh.cleanup.
// This really should be elsewhere in the function.
// CHECK-EH: resume { i8*, i32 }
// %terminate.lpad: terminate landing pad.
// CHECK-EH-03: [[T0:%.*]] = landingpad { i8*, i32 }
// CHECK-EH-03-NEXT: catch i8* null
// CHECK-EH-03-NEXT: [[T1:%.*]] = extractvalue { i8*, i32 } [[T0]], 0
// CHECK-EH-03-NEXT: call void @__clang_call_terminate(i8* [[T1]]) [[NR_NUW:#[0-9]+]]
// CHECK-EH-03-NEXT: unreachable
}
// CHECK-LABEL: define void @_Z5test3b
X test3(bool B) {
// CHECK: call {{.*}} @_ZN1XC1Ev
// CHECK-NOT: call {{.*}} @_ZN1XC1ERKS_
// CHECK: call {{.*}} @_ZN1XC1Ev
// CHECK: call {{.*}} @_ZN1XC1ERKS_
if (B) {
X y;
return y;
}
// FIXME: we should NRVO this variable too.
X x;
return x;
}
extern "C" void exit(int) throw();
// CHECK-LABEL: define void @_Z5test4b
X test4(bool B) {
{
// CHECK: call {{.*}} @_ZN1XC1Ev
X x;
// CHECK: br i1
if (B)
return x;
}
// CHECK: call {{.*}} @_ZN1XD1Ev
// CHECK: call void @exit(i32 1)
exit(1);
}
#ifdef __EXCEPTIONS
// CHECK-EH-LABEL: define void @_Z5test5
void may_throw();
X test5() {
try {
may_throw();
} catch (X x) {
// CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_
// CHECK-EH: call void @__cxa_end_catch()
// CHECK-EH: ret void
return x;
}
}
#endif
// rdar://problem/10430868
// CHECK-LABEL: define void @_Z5test6v
X test6() {
X a __attribute__((aligned(8)));
return a;
// CHECK: [[A:%.*]] = alloca [[X:%.*]], align 8
// CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds %class.X, %class.X* [[A]], i32 0, i32 0
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[PTR]])
// CHECK-NEXT: call {{.*}} @_ZN1XC1Ev([[X]]* nonnull [[A]])
// CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_([[X]]* {{%.*}}, [[X]]* nonnull dereferenceable({{[0-9]+}}) [[A]])
// CHECK-NEXT: call {{.*}} @_ZN1XD1Ev([[X]]* nonnull [[A]])
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[PTR]])
// CHECK-NEXT: ret void
}
// CHECK-LABEL: define void @_Z5test7b
X test7(bool b) {
// CHECK: call {{.*}} @_ZN1XC1Ev
// CHECK-NEXT: ret
if (b) {
X x;
return x;
}
return X();
}
// CHECK-LABEL: define void @_Z5test8b
X test8(bool b) {
// CHECK: call {{.*}} @_ZN1XC1Ev
// CHECK-NEXT: ret
if (b) {
X x;
return x;
} else {
X y;
return y;
}
}
Y<int> test9() {
Y<int>::f();
}
// CHECK-LABEL: define linkonce_odr void @_ZN1YIiE1fEv
// CHECK: call {{.*}} @_ZN1YIiEC1Ev
// CHECK-EH-03: attributes [[NR_NUW]] = { noreturn nounwind }