mirror of
https://github.com/Gericom/teak-llvm.git
synced 2025-06-19 11:35:51 -04:00

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 commitc9ddb02659
.
224 lines
6.0 KiB
C++
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 }
|