This reapplies: 8ff85ed905a7306977d07a5cd67ab4d5a56fafb4 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 c9ddb02659e3ece7a0d9d6b4dac7ceea4ae46e6d.
147 lines
3.7 KiB
C++
147 lines
3.7 KiB
C++
// RUN: %clang_cc1 -triple armv7-unknown-linux-gnueabihf %s -o - -emit-llvm -O2 | FileCheck %s
|
|
|
|
// Stack should be reused when possible, no need to allocate two separate slots
|
|
// if they have disjoint lifetime.
|
|
|
|
// Sizes of objects are related to previously existed threshold of 32. In case
|
|
// of S_large stack size is rounded to 40 bytes.
|
|
|
|
// 32B
|
|
struct S_small {
|
|
int a[8];
|
|
};
|
|
|
|
// 36B
|
|
struct S_large {
|
|
int a[9];
|
|
};
|
|
|
|
// Helper class for lifetime scope absence testing
|
|
struct Combiner {
|
|
S_large a, b;
|
|
|
|
Combiner(S_large);
|
|
Combiner f();
|
|
};
|
|
|
|
extern S_small foo_small();
|
|
extern S_large foo_large();
|
|
extern void bar_small(S_small*);
|
|
extern void bar_large(S_large*);
|
|
|
|
// Prevent mangling of function names.
|
|
extern "C" {
|
|
|
|
void small_rvoed_unnamed_temporary_object() {
|
|
// CHECK-LABEL: define void @small_rvoed_unnamed_temporary_object
|
|
// CHECK: call void @llvm.lifetime.start
|
|
// CHECK: call void @_Z9foo_smallv
|
|
// CHECK: call void @llvm.lifetime.end
|
|
// CHECK: call void @llvm.lifetime.start
|
|
// CHECK: call void @_Z9foo_smallv
|
|
// CHECK: call void @llvm.lifetime.end
|
|
|
|
foo_small();
|
|
foo_small();
|
|
}
|
|
|
|
void large_rvoed_unnamed_temporary_object() {
|
|
// CHECK-LABEL: define void @large_rvoed_unnamed_temporary_object
|
|
// CHECK: call void @llvm.lifetime.start
|
|
// CHECK: call void @_Z9foo_largev
|
|
// CHECK: call void @llvm.lifetime.end
|
|
// CHECK: call void @llvm.lifetime.start
|
|
// CHECK: call void @_Z9foo_largev
|
|
// CHECK: call void @llvm.lifetime.end
|
|
|
|
foo_large();
|
|
foo_large();
|
|
}
|
|
|
|
void small_rvoed_named_temporary_object() {
|
|
// CHECK-LABEL: define void @small_rvoed_named_temporary_object
|
|
// CHECK: call void @llvm.lifetime.start
|
|
// CHECK: call void @_Z9foo_smallv
|
|
// CHECK: call void @llvm.lifetime.end
|
|
// CHECK: call void @llvm.lifetime.start
|
|
// CHECK: call void @_Z9foo_smallv
|
|
// CHECK: call void @llvm.lifetime.end
|
|
|
|
{
|
|
S_small s = foo_small();
|
|
}
|
|
{
|
|
S_small s = foo_small();
|
|
}
|
|
}
|
|
|
|
void large_rvoed_named_temporary_object() {
|
|
// CHECK-LABEL: define void @large_rvoed_named_temporary_object
|
|
// CHECK: call void @llvm.lifetime.start
|
|
// CHECK: call void @_Z9foo_largev
|
|
// CHECK: call void @llvm.lifetime.end
|
|
// CHECK: call void @llvm.lifetime.start
|
|
// CHECK: call void @_Z9foo_largev
|
|
// CHECK: call void @llvm.lifetime.end
|
|
|
|
{
|
|
S_large s = foo_large();
|
|
}
|
|
{
|
|
S_large s = foo_large();
|
|
}
|
|
}
|
|
|
|
void small_auto_object() {
|
|
// CHECK-LABEL: define void @small_auto_object
|
|
// CHECK: call void @llvm.lifetime.start
|
|
// CHECK: call void @_Z9bar_smallP7S_small
|
|
// CHECK: call void @llvm.lifetime.end
|
|
// CHECK: call void @llvm.lifetime.start
|
|
// CHECK: call void @_Z9bar_smallP7S_small
|
|
// CHECK: call void @llvm.lifetime.end
|
|
|
|
{
|
|
S_small s;
|
|
bar_small(&s);
|
|
}
|
|
{
|
|
S_small s;
|
|
bar_small(&s);
|
|
}
|
|
}
|
|
|
|
void large_auto_object() {
|
|
// CHECK-LABEL: define void @large_auto_object
|
|
// CHECK: call void @llvm.lifetime.start
|
|
// CHECK: call void @_Z9bar_largeP7S_large
|
|
// CHECK: call void @llvm.lifetime.end
|
|
// CHECK: call void @llvm.lifetime.start
|
|
// CHECK: call void @_Z9bar_largeP7S_large
|
|
// CHECK: call void @llvm.lifetime.end
|
|
|
|
{
|
|
S_large s;
|
|
bar_large(&s);
|
|
}
|
|
{
|
|
S_large s;
|
|
bar_large(&s);
|
|
}
|
|
}
|
|
|
|
int large_combiner_test(S_large s) {
|
|
// CHECK-LABEL: define i32 @large_combiner_test
|
|
// CHECK: [[T2:%.*]] = alloca %struct.Combiner
|
|
// CHECK: [[T1:%.*]] = alloca %struct.Combiner
|
|
// CHECK: [[T3:%.*]] = call %struct.Combiner* @_ZN8CombinerC1E7S_large(%struct.Combiner* nonnull [[T1]], [9 x i32] %s.coerce)
|
|
// CHECK: call void @_ZN8Combiner1fEv(%struct.Combiner* nonnull sret [[T2]], %struct.Combiner* nonnull [[T1]])
|
|
// CHECK: [[T4:%.*]] = getelementptr inbounds %struct.Combiner, %struct.Combiner* [[T2]], i32 0, i32 0, i32 0, i32 0
|
|
// CHECK: [[T5:%.*]] = load i32, i32* [[T4]]
|
|
// CHECK: ret i32 [[T5]]
|
|
|
|
return Combiner(s).f().a.a[0];
|
|
}
|
|
|
|
}
|